<!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <meta name="generator" content="VuePress 2.0.0-beta.48" />
    <meta name="theme" content="VuePress Theme Hope" />
    <meta property="og:url" content="https://vuepress-theme-hope-v2-demo.mrhope.site/zh/interview/Java%E5%AE%B9%E5%99%A8.html"><meta property="og:site_name" content="主题演示"><meta property="og:title" content="Java容器"><meta property="og:type" content="article"><meta property="og:locale" content="zh-CN"><meta property="og:locale:alternate" content="en-US"><meta property="article:tag" content="Java容器"><title>Java容器 | 主题演示</title><meta name="description" content="vuepress-theme-hope 的演示">
    <style>
      :root {
        --bg-color: #fff;
      }

      html[data-theme="dark"] {
        --bg-color: #1d2025;
      }

      html,
      body {
        background-color: var(--bg-color);
      }
    </style>
    <script>
      const userMode = localStorage.getItem("vuepress-theme-hope-scheme");
      const systemDarkMode =
        window.matchMedia &&
        window.matchMedia("(prefers-color-scheme: dark)").matches;

      if (userMode === "dark" || (userMode !== "light" && systemDarkMode)) {
        document.querySelector("html").setAttribute("data-theme", "dark");
      }
    </script>
    <link rel="stylesheet" href="/assets/style.dbbe025d.css">
    <link rel="modulepreload" href="/assets/app.e732cc94.js"><link rel="modulepreload" href="/assets/Java容器.html.5139503a.js"><link rel="modulepreload" href="/assets/plugin-vue_export-helper.21dcd24c.js"><link rel="modulepreload" href="/assets/Java容器.html.77448ff5.js"><link rel="prefetch" href="/assets/home.html.d675c4b6.js"><link rel="prefetch" href="/assets/intro.html.684ef626.js"><link rel="prefetch" href="/assets/index.html.e8ffec66.js"><link rel="prefetch" href="/assets/slide.html.050a6f1e.js"><link rel="prefetch" href="/assets/disable.html.b507ecac.js"><link rel="prefetch" href="/assets/encrypt.html.762116d5.js"><link rel="prefetch" href="/assets/markdown.html.5acf7a9a.js"><link rel="prefetch" href="/assets/page.html.141b0147.js"><link rel="prefetch" href="/assets/index.html.75bf4c69.js"><link rel="prefetch" href="/assets/article10.html.f5ea4d77.js"><link rel="prefetch" href="/assets/article11.html.6339c214.js"><link rel="prefetch" href="/assets/article12.html.5ac86a8f.js"><link rel="prefetch" href="/assets/article9.html.666c37a0.js"><link rel="prefetch" href="/assets/home.html.6e361c52.js"><link rel="prefetch" href="/assets/index.html.2d9b62a7.js"><link rel="prefetch" href="/assets/slide.html.6b655fa0.js"><link rel="prefetch" href="/assets/article1.html.f835efef.js"><link rel="prefetch" href="/assets/article2.html.e4775195.js"><link rel="prefetch" href="/assets/article3.html.bfdf934f.js"><link rel="prefetch" href="/assets/article4.html.69bccee4.js"><link rel="prefetch" href="/assets/article5.html.c7ac5439.js"><link rel="prefetch" href="/assets/article6.html.880c0652.js"><link rel="prefetch" href="/assets/article7.html.2cae84db.js"><link rel="prefetch" href="/assets/article8.html.6c46837c.js"><link rel="prefetch" href="/assets/disable.html.f629efab.js"><link rel="prefetch" href="/assets/encrypt.html.58d61689.js"><link rel="prefetch" href="/assets/markdown.html.779c42bf.js"><link rel="prefetch" href="/assets/page.html.125d74f5.js"><link rel="prefetch" href="/assets/index.html.3db704fb.js"><link rel="prefetch" href="/assets/article10.html.b5d65d2d.js"><link rel="prefetch" href="/assets/article11.html.b2cf93ee.js"><link rel="prefetch" href="/assets/article12.html.94e1cf22.js"><link rel="prefetch" href="/assets/article9.html.90cf2a62.js"><link rel="prefetch" href="/assets/Docker.html.de1063e8.js"><link rel="prefetch" href="/assets/Java基础.html.6c0b0f5c.js"><link rel="prefetch" href="/assets/JUC.html.76307785.js"><link rel="prefetch" href="/assets/JVM.html.0bb340ff.js"><link rel="prefetch" href="/assets/Linux.html.90ea1c3b.js"><link rel="prefetch" href="/assets/MySQL.html.73ae62bf.js"><link rel="prefetch" href="/assets/NIO与Netty.html.a73529b1.js"><link rel="prefetch" href="/assets/index.html.2a38d188.js"><link rel="prefetch" href="/assets/Redis.html.78427b11.js"><link rel="prefetch" href="/assets/主流框架.html.f21f66df.js"><link rel="prefetch" href="/assets/分布式与高性能高可用.html.38ab4746.js"><link rel="prefetch" href="/assets/操作系统.html.76b600e3.js"><link rel="prefetch" href="/assets/智力题.html.ec368cec.js"><link rel="prefetch" href="/assets/系统设计.html.fb8f2074.js"><link rel="prefetch" href="/assets/计算机网络.html.1a7f7d0e.js"><link rel="prefetch" href="/assets/设计模式.html.cd48ccf5.js"><link rel="prefetch" href="/assets/article1.html.ca54de60.js"><link rel="prefetch" href="/assets/article2.html.a99d479f.js"><link rel="prefetch" href="/assets/article3.html.5a2797ee.js"><link rel="prefetch" href="/assets/article4.html.3ac5a509.js"><link rel="prefetch" href="/assets/article5.html.c09d20ba.js"><link rel="prefetch" href="/assets/article6.html.c9e59f52.js"><link rel="prefetch" href="/assets/article7.html.948e77cc.js"><link rel="prefetch" href="/assets/article8.html.28c3977f.js"><link rel="prefetch" href="/assets/404.html.8a909211.js"><link rel="prefetch" href="/assets/index.html.690b188a.js"><link rel="prefetch" href="/assets/index.html.6085d793.js"><link rel="prefetch" href="/assets/index.html.932078ca.js"><link rel="prefetch" href="/assets/index.html.bb629f30.js"><link rel="prefetch" href="/assets/index.html.92b2d70c.js"><link rel="prefetch" href="/assets/index.html.82840baf.js"><link rel="prefetch" href="/assets/index.html.85406aa8.js"><link rel="prefetch" href="/assets/index.html.7b9124b8.js"><link rel="prefetch" href="/assets/index.html.e1e2a548.js"><link rel="prefetch" href="/assets/index.html.a9a69593.js"><link rel="prefetch" href="/assets/index.html.5b51b72b.js"><link rel="prefetch" href="/assets/index.html.ec7f0295.js"><link rel="prefetch" href="/assets/index.html.e14e2286.js"><link rel="prefetch" href="/assets/index.html.e89216be.js"><link rel="prefetch" href="/assets/index.html.c0adb933.js"><link rel="prefetch" href="/assets/index.html.a45798a3.js"><link rel="prefetch" href="/assets/index.html.e99c516b.js"><link rel="prefetch" href="/assets/index.html.f6be7fb4.js"><link rel="prefetch" href="/assets/index.html.6812b391.js"><link rel="prefetch" href="/assets/index.html.4bae905e.js"><link rel="prefetch" href="/assets/index.html.0599248b.js"><link rel="prefetch" href="/assets/index.html.963b2596.js"><link rel="prefetch" href="/assets/index.html.bbd9778f.js"><link rel="prefetch" href="/assets/index.html.c6a7a8d4.js"><link rel="prefetch" href="/assets/index.html.13391f8f.js"><link rel="prefetch" href="/assets/index.html.4b0a0f3f.js"><link rel="prefetch" href="/assets/index.html.bbd06d0d.js"><link rel="prefetch" href="/assets/index.html.9a4d8710.js"><link rel="prefetch" href="/assets/index.html.dfdff039.js"><link rel="prefetch" href="/assets/index.html.cd21ad11.js"><link rel="prefetch" href="/assets/index.html.72b3c545.js"><link rel="prefetch" href="/assets/index.html.0262e65d.js"><link rel="prefetch" href="/assets/index.html.8905ca40.js"><link rel="prefetch" href="/assets/index.html.98e54f53.js"><link rel="prefetch" href="/assets/index.html.707c5120.js"><link rel="prefetch" href="/assets/index.html.daf3ede2.js"><link rel="prefetch" href="/assets/index.html.ae769b93.js"><link rel="prefetch" href="/assets/index.html.59a75e1b.js"><link rel="prefetch" href="/assets/index.html.efb1d101.js"><link rel="prefetch" href="/assets/index.html.898df6f8.js"><link rel="prefetch" href="/assets/index.html.6339ac7f.js"><link rel="prefetch" href="/assets/index.html.0ffdd311.js"><link rel="prefetch" href="/assets/index.html.454f52cf.js"><link rel="prefetch" href="/assets/index.html.d8a5ddde.js"><link rel="prefetch" href="/assets/index.html.3be06723.js"><link rel="prefetch" href="/assets/index.html.1d180388.js"><link rel="prefetch" href="/assets/index.html.337241b0.js"><link rel="prefetch" href="/assets/index.html.0be3cd3f.js"><link rel="prefetch" href="/assets/index.html.8e5505d4.js"><link rel="prefetch" href="/assets/index.html.ffdd1452.js"><link rel="prefetch" href="/assets/index.html.d3825f4c.js"><link rel="prefetch" href="/assets/home.html.ccae7996.js"><link rel="prefetch" href="/assets/intro.html.fd34d8e1.js"><link rel="prefetch" href="/assets/index.html.ba786069.js"><link rel="prefetch" href="/assets/slide.html.0df38877.js"><link rel="prefetch" href="/assets/disable.html.6465acbf.js"><link rel="prefetch" href="/assets/encrypt.html.f697c2c7.js"><link rel="prefetch" href="/assets/markdown.html.f534aa4c.js"><link rel="prefetch" href="/assets/page.html.d91d46f6.js"><link rel="prefetch" href="/assets/index.html.b66745bd.js"><link rel="prefetch" href="/assets/article10.html.a245f19a.js"><link rel="prefetch" href="/assets/article11.html.c7128e02.js"><link rel="prefetch" href="/assets/article12.html.abd25c27.js"><link rel="prefetch" href="/assets/article9.html.7bba6b9f.js"><link rel="prefetch" href="/assets/home.html.eb29b64c.js"><link rel="prefetch" href="/assets/index.html.a51898c1.js"><link rel="prefetch" href="/assets/slide.html.4db0d16b.js"><link rel="prefetch" href="/assets/article1.html.8aeaf420.js"><link rel="prefetch" href="/assets/article2.html.1b3af75b.js"><link rel="prefetch" href="/assets/article3.html.83bc62c6.js"><link rel="prefetch" href="/assets/article4.html.9c3e20ef.js"><link rel="prefetch" href="/assets/article5.html.a86dfd69.js"><link rel="prefetch" href="/assets/article6.html.1005b310.js"><link rel="prefetch" href="/assets/article7.html.e62a511b.js"><link rel="prefetch" href="/assets/article8.html.5d7e1f67.js"><link rel="prefetch" href="/assets/disable.html.9d48f34e.js"><link rel="prefetch" href="/assets/encrypt.html.69059b41.js"><link rel="prefetch" href="/assets/markdown.html.f8f89db4.js"><link rel="prefetch" href="/assets/page.html.f139635c.js"><link rel="prefetch" href="/assets/index.html.126e92a0.js"><link rel="prefetch" href="/assets/article10.html.f00bfbec.js"><link rel="prefetch" href="/assets/article11.html.4e4aea0e.js"><link rel="prefetch" href="/assets/article12.html.ed056ef8.js"><link rel="prefetch" href="/assets/article9.html.c3cb96a4.js"><link rel="prefetch" href="/assets/Docker.html.f45c96a5.js"><link rel="prefetch" href="/assets/Java基础.html.56267f30.js"><link rel="prefetch" href="/assets/JUC.html.ebe8f287.js"><link rel="prefetch" href="/assets/JVM.html.c448b42c.js"><link rel="prefetch" href="/assets/Linux.html.43840acf.js"><link rel="prefetch" href="/assets/MySQL.html.eba28d84.js"><link rel="prefetch" href="/assets/NIO与Netty.html.66d42188.js"><link rel="prefetch" href="/assets/index.html.f3cc61a2.js"><link rel="prefetch" href="/assets/Redis.html.d810a669.js"><link rel="prefetch" href="/assets/主流框架.html.48ca457c.js"><link rel="prefetch" href="/assets/分布式与高性能高可用.html.a85c8cdb.js"><link rel="prefetch" href="/assets/操作系统.html.c2f0370c.js"><link rel="prefetch" href="/assets/智力题.html.4d751983.js"><link rel="prefetch" href="/assets/系统设计.html.c1542e9d.js"><link rel="prefetch" href="/assets/计算机网络.html.724e0903.js"><link rel="prefetch" href="/assets/设计模式.html.2465754d.js"><link rel="prefetch" href="/assets/article1.html.ac18bda1.js"><link rel="prefetch" href="/assets/article2.html.051f8867.js"><link rel="prefetch" href="/assets/article3.html.ebe7849b.js"><link rel="prefetch" href="/assets/article4.html.a4dbc976.js"><link rel="prefetch" href="/assets/article5.html.395a5403.js"><link rel="prefetch" href="/assets/article6.html.74c49cbf.js"><link rel="prefetch" href="/assets/article7.html.bf053e97.js"><link rel="prefetch" href="/assets/article8.html.7213c414.js"><link rel="prefetch" href="/assets/404.html.22aaa4fc.js"><link rel="prefetch" href="/assets/index.html.bd6ff77c.js"><link rel="prefetch" href="/assets/index.html.a7880d9d.js"><link rel="prefetch" href="/assets/index.html.f5f99f6a.js"><link rel="prefetch" href="/assets/index.html.561cd4cd.js"><link rel="prefetch" href="/assets/index.html.2b2206fe.js"><link rel="prefetch" href="/assets/index.html.ec6b7467.js"><link rel="prefetch" href="/assets/index.html.146ab8c4.js"><link rel="prefetch" href="/assets/index.html.f201f6e8.js"><link rel="prefetch" href="/assets/index.html.a1a6c5d4.js"><link rel="prefetch" href="/assets/index.html.61b33c23.js"><link rel="prefetch" href="/assets/index.html.8640e57f.js"><link rel="prefetch" href="/assets/index.html.c3d0fc1d.js"><link rel="prefetch" href="/assets/index.html.461f8cdf.js"><link rel="prefetch" href="/assets/index.html.1dea7bef.js"><link rel="prefetch" href="/assets/index.html.e6addda8.js"><link rel="prefetch" href="/assets/index.html.2638e7e9.js"><link rel="prefetch" href="/assets/index.html.5db2b8e8.js"><link rel="prefetch" href="/assets/index.html.cbff7fea.js"><link rel="prefetch" href="/assets/index.html.5ac21d40.js"><link rel="prefetch" href="/assets/index.html.c7acfbee.js"><link rel="prefetch" href="/assets/index.html.fb44feb1.js"><link rel="prefetch" href="/assets/index.html.d4e476c9.js"><link rel="prefetch" href="/assets/index.html.ec5764c9.js"><link rel="prefetch" href="/assets/index.html.d185c9f1.js"><link rel="prefetch" href="/assets/index.html.0867f7ab.js"><link rel="prefetch" href="/assets/index.html.2c3899c7.js"><link rel="prefetch" href="/assets/index.html.8a2aee35.js"><link rel="prefetch" href="/assets/index.html.130e4c85.js"><link rel="prefetch" href="/assets/index.html.7277b095.js"><link rel="prefetch" href="/assets/index.html.c074ddbd.js"><link rel="prefetch" href="/assets/index.html.e91a40c5.js"><link rel="prefetch" href="/assets/index.html.0b2b027d.js"><link rel="prefetch" href="/assets/index.html.6b602146.js"><link rel="prefetch" href="/assets/index.html.16d4af72.js"><link rel="prefetch" href="/assets/index.html.b8fc0dcc.js"><link rel="prefetch" href="/assets/index.html.9b3fcbd9.js"><link rel="prefetch" href="/assets/index.html.eeb89bf7.js"><link rel="prefetch" href="/assets/index.html.5114cd1e.js"><link rel="prefetch" href="/assets/index.html.b8354286.js"><link rel="prefetch" href="/assets/index.html.fcd579df.js"><link rel="prefetch" href="/assets/index.html.e743d320.js"><link rel="prefetch" href="/assets/index.html.b34f28e1.js"><link rel="prefetch" href="/assets/index.html.dd5dd927.js"><link rel="prefetch" href="/assets/index.html.7df41339.js"><link rel="prefetch" href="/assets/index.html.9de9b7ae.js"><link rel="prefetch" href="/assets/index.html.db158b25.js"><link rel="prefetch" href="/assets/index.html.fcab0b26.js"><link rel="prefetch" href="/assets/index.html.afada1db.js"><link rel="prefetch" href="/assets/index.html.8681058b.js"><link rel="prefetch" href="/assets/index.html.1c990d16.js"><link rel="prefetch" href="/assets/index.html.9563932e.js"><link rel="prefetch" href="/assets/404.4ba82410.js"><link rel="prefetch" href="/assets/Layout.67323a43.js"><link rel="prefetch" href="/assets/Slide.be972901.js"><link rel="prefetch" href="/assets/Blog.caaad5e4.js"><link rel="prefetch" href="/assets/giscus.es.63137db5.js"><link rel="prefetch" href="/assets/auto.esm.36809f22.js"><link rel="prefetch" href="/assets/index.daae04bf.js"><link rel="prefetch" href="/assets/index.1842ee54.js"><link rel="prefetch" href="/assets/mermaid.esm.min.ee1e0284.js"><link rel="prefetch" href="/assets/highlight.esm.d982e650.js"><link rel="prefetch" href="/assets/markdown.esm.832a189d.js"><link rel="prefetch" href="/assets/math.esm.a3f84b6f.js"><link rel="prefetch" href="/assets/notes.esm.3c361cb7.js"><link rel="prefetch" href="/assets/reveal.esm.b96f05d8.js"><link rel="prefetch" href="/assets/search.esm.80da4a02.js"><link rel="prefetch" href="/assets/zoom.esm.8514a202.js"><link rel="prefetch" href="/assets/photoswipe.esm.092fbc15.js">
  </head>
  <body>
    <div id="app"><!--[--><!--[--><!--[--><span tabindex="-1"></span><a href="#main-content" class="skip-link sr-only">Skip to content</a><!--]--><div class="theme-container has-toc"><!--[--><!--[--><header class="navbar"><div class="navbar-left"><button class="toggle-sidebar-button" title="Toggle Sidebar"><span class="icon"></span></button><!----><a href="/zh/" class="brand"><img class="logo" src="/logo.svg" alt="主题演示"><!----><span class="site-name hide-in-pad">主题演示</span></a><!----></div><div class="navbar-center"><!----><nav class="nav-links"><div class="nav-item hide-in-mobile"><a href="/zh/" class="nav-link" aria-label="博客主页"><span class="icon iconfont icon-home" style=""></span>博客主页<!----></a></div><div class="nav-item hide-in-mobile"><a href="/zh/home.html" class="nav-link" aria-label="项目主页"><span class="icon iconfont icon-home" style=""></span>项目主页<!----></a></div><div class="nav-item hide-in-mobile"><a href="/zh/guide/" class="nav-link" aria-label="使用指南"><span class="icon iconfont icon-creative" style=""></span>使用指南<!----></a></div><div class="nav-item hide-in-mobile"><div class="dropdown-wrapper"><button class="dropdown-title" type="button" aria-label="博文"><span class="title"><span class="icon iconfont icon-edit" style=""></span>博文</span><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><h4 class="dropdown-subtitle"><span>文章 1-4</span></h4><ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/zh/posts/article/article1.html" class="nav-link" aria-label="文章 1"><span class="icon iconfont icon-edit" style=""></span>文章 1<!----></a></li><li class="dropdown-subitem"><a href="/zh/posts/article/article2.html" class="nav-link" aria-label="文章 2"><span class="icon iconfont icon-edit" style=""></span>文章 2<!----></a></li><li class="dropdown-subitem"><a href="/zh/posts/article/article3.html" class="nav-link" aria-label="文章 3"><span class="icon iconfont icon-edit" style=""></span>文章 3<!----></a></li><li class="dropdown-subitem"><a href="/zh/posts/article/article4.html" class="nav-link" aria-label="文章 4"><span class="icon iconfont icon-edit" style=""></span>文章 4<!----></a></li></ul></li><li class="dropdown-item"><h4 class="dropdown-subtitle"><span>文章 5-12</span></h4><ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/zh/posts/article/article5.html" class="nav-link" aria-label="文章 5"><span class="icon iconfont icon-edit" style=""></span>文章 5<!----></a></li><li class="dropdown-subitem"><a href="/zh/posts/article/article6.html" class="nav-link" aria-label="文章 6"><span class="icon iconfont icon-edit" style=""></span>文章 6<!----></a></li><li class="dropdown-subitem"><a href="/zh/posts/article/article7.html" class="nav-link" aria-label="文章 7"><span class="icon iconfont icon-edit" style=""></span>文章 7<!----></a></li><li class="dropdown-subitem"><a href="/zh/posts/article/article8.html" class="nav-link" aria-label="文章 8"><span class="icon iconfont icon-edit" style=""></span>文章 8<!----></a></li></ul></li><li class="dropdown-item"><a href="/zh/posts/article9.html" class="nav-link" aria-label="文章 9"><span class="icon iconfont icon-edit" style=""></span>文章 9<!----></a></li><li class="dropdown-item"><a href="/zh/posts/article10.html" class="nav-link" aria-label="文章 10"><span class="icon iconfont icon-edit" style=""></span>文章 10<!----></a></li><li class="dropdown-item"><a href="/zh/posts/article11.html" class="nav-link" aria-label="文章 11"><span class="icon iconfont icon-edit" style=""></span>文章 11<!----></a></li><li class="dropdown-item"><a href="/zh/posts/article12.html" class="nav-link" aria-label="文章 12"><span class="icon iconfont icon-edit" style=""></span>文章 12<!----></a></li></ul></button></div></div><div class="nav-item hide-in-mobile"><a href="https://vuepress-theme-hope.github.io/v2/zh/" rel="noopener noreferrer" target="_blank" aria-label="主题文档" class="nav-link"><span class="icon iconfont icon-note" style=""></span>主题文档<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div></nav><!----></div><div class="navbar-right"><!----><div class="nav-item"><div class="dropdown-wrapper i18n-dropdown"><button class="dropdown-title" type="button" aria-label="选择语言"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon i18n-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="i18n icon" style="width:1rem;height:1rem;vertical-align:middle;"><path d="M379.392 460.8 494.08 575.488l-42.496 102.4L307.2 532.48 138.24 701.44l-71.68-72.704L234.496 460.8l-45.056-45.056c-27.136-27.136-51.2-66.56-66.56-108.544h112.64c7.68 14.336 16.896 27.136 26.112 35.84l45.568 46.08 45.056-45.056C382.976 312.32 409.6 247.808 409.6 204.8H0V102.4h256V0h102.4v102.4h256v102.4H512c0 70.144-37.888 161.28-87.04 210.944L378.88 460.8zM576 870.4 512 1024H409.6l256-614.4H768l256 614.4H921.6l-64-153.6H576zM618.496 768h196.608L716.8 532.48 618.496 768z"></path></svg><!--]--><span class="arrow"></span><ul class="nav-dropdown"><li class="dropdown-item"><a href="/" class="nav-link" aria-label="English"><!---->English<!----></a></li><li class="dropdown-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html" class="router-link-active router-link-exact-active nav-link active" aria-label="简体中文"><!---->简体中文<!----></a></li></ul></button></div></div><div class="nav-item"><a class="repo-link" href="https://gitee.com/changluJava/personal-reading" target="_blank" rel="noopener noreferrer" aria-label="Gitee"><svg xmlns="http://www.w3.org/2000/svg" class="icon gitee-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="gitee icon" style="width:1.25rem;height:1.25rem;vertical-align:middle;"><path d="M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm242.97-533.34H482.39a23.7 23.7 0 0 0-23.7 23.7l-.03 59.28c0 13.08 10.59 23.7 23.7 23.7h165.96a23.7 23.7 0 0 1 23.7 23.7v11.85a71.1 71.1 0 0 1-71.1 71.1H375.71a23.7 23.7 0 0 1-23.7-23.7V423.11a71.1 71.1 0 0 1 71.1-71.1h331.8a23.7 23.7 0 0 0 23.7-23.7l.06-59.25a23.73 23.73 0 0 0-23.7-23.73H423.11a177.78 177.78 0 0 0-177.78 177.75v331.83c0 13.08 10.62 23.7 23.7 23.7h349.62a159.99 159.99 0 0 0 159.99-159.99V482.33a23.7 23.7 0 0 0-23.7-23.7z"></path></svg></a></div><div class="nav-item hide-in-mobile"><button id="appearance-switch"><svg xmlns="http://www.w3.org/2000/svg" class="icon auto-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="auto icon" style="display:block;"><path d="M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="dark icon" style="display:none;"><path d="M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="light icon" style="display:none;"><path d="M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"></path></svg></button></div><!----><!----><button class="toggle-navbar-button" aria-label="Toggle Navbar" aria-expanded="false" aria-controls="nav-screen"><span class="button-container"><span class="button-top"></span><span class="button-middle"></span><span class="button-bottom"></span></span></button></div></header><!----><!--]--><!----><div class="toggle-sidebar-wrapper"><span class="arrow left"></span></div><aside class="sidebar"><!--[--><!----><!--]--><ul class="sidebar-links"><li><!--[--><a href="/zh/" class="nav-link sidebar-link sidebar-page" aria-label="博客主页"><span class="icon iconfont icon-home" style=""></span>博客主页<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/home.html" class="nav-link sidebar-link sidebar-page" aria-label="项目主页"><span class="icon iconfont icon-home" style=""></span>项目主页<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/slide" class="nav-link sidebar-link sidebar-page" aria-label="幻灯片"><!---->幻灯片<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><span class="icon iconfont icon-creative" style=""></span><a href="/zh/interview/" class="title">面试指南</a><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><a href="/zh/interview/Docker.html" class="nav-link sidebar-link sidebar-page" aria-label="Docker"><span class="icon iconfont icon-lock" style=""></span>Docker<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/Java%E5%9F%BA%E7%A1%80.html" class="nav-link sidebar-link sidebar-page" aria-label="JAVA"><span class="icon iconfont icon-lock" style=""></span>JAVA<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html" class="router-link-active router-link-exact-active nav-link active sidebar-link sidebar-page active" aria-label="Java容器"><span class="icon iconfont icon-lock" style=""></span>Java容器<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_1、java的集合有哪些" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="1、Java的集合有哪些？"><!---->1、Java的集合有哪些？<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_2、说说-list-set-queue-map-四者的区别" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="2、说说 List, Set, Queue, Map 四者的区别？"><!---->2、说说 List, Set, Queue, Map 四者的区别？<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_3、集合框架底层数据结构总结" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="3、集合框架底层数据结构总结"><!---->3、集合框架底层数据结构总结<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_4、如何选用集合" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="4、如何选用集合？"><!---->4、如何选用集合？<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_5、为什么要使用集合" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="5、为什么要使用集合？"><!---->5、为什么要使用集合？<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#collection-子接口之-list" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="Collection 子接口之 List"><!---->Collection 子接口之 List<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#arrarylist" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="ArraryList"><!---->ArraryList<!----></a><ul class="sidebar-sub-headers"></ul></li></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#collection-子接口之-set" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="Collection 子接口之 Set"><!---->Collection 子接口之 Set<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_1、comparable-和-comparator-的区别" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="1、comparable 和 Comparator 的区别"><!---->1、comparable 和 Comparator 的区别<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_2、无序性和不可重复性的含义是什么" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="2、无序性和不可重复性的含义是什么"><!---->2、无序性和不可重复性的含义是什么<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_3、比较-hashset、linkedhashset-和-treeset-三者的异同" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="3、比较 HashSet、LinkedHashSet 和 TreeSet 三者的异同"><!---->3、比较 HashSet、LinkedHashSet 和 TreeSet 三者的异同<!----></a><ul class="sidebar-sub-headers"></ul></li></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#collection-子接口之-queue" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="Collection 子接口之 Queue"><!---->Collection 子接口之 Queue<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_1、queue-与-deque-的区别" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="1、Queue 与 Deque 的区别"><!---->1、Queue 与 Deque 的区别<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_2、arraydeque-与-linkedlist-的区别" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="2、ArrayDeque 与 LinkedList 的区别"><!---->2、ArrayDeque 与 LinkedList 的区别<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_3、说一说-priorityqueue" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="3、说一说 PriorityQueue"><!---->3、说一说 PriorityQueue<!----></a><ul class="sidebar-sub-headers"></ul></li></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#hashmap" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="HashMap"><!---->HashMap<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_1、hashmap的原理-内部的数据结构" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="1、HashMap的原理，内部的数据结构"><!---->1、HashMap的原理，内部的数据结构<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_2、put-方法讲一下" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="2、put()方法讲一下"><!---->2、put()方法讲一下<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_3、hashmap中hash函数怎么是实现的" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="3、HashMap中hash函数怎么是实现的?"><!---->3、HashMap中hash函数怎么是实现的?<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_4、为什么hashmap中的-位数必须为奇数-length-1" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="4、为什么HashMap中的&amp;位数必须为奇数（Length-1）"><!---->4、为什么HashMap中的&amp;位数必须为奇数（Length-1）<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_5、常见的哈希函数以及哈希碰撞解决方案" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="5、常见的哈希函数以及哈希碰撞解决方案"><!---->5、常见的哈希函数以及哈希碰撞解决方案<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_6、红黑树的特点" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="6、红黑树的特点"><!---->6、红黑树的特点<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_7、不使用锁如何改造hashmap使其线程安全-redis" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="7、不使用锁如何改造Hashmap使其线程安全（redis）"><!---->7、不使用锁如何改造Hashmap使其线程安全（redis）<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#hashset" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="HashSet"><!---->HashSet<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#容量、扩容问题" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="容量、扩容问题"><!---->容量、扩容问题<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#jdk1-7问题" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="JDK1.7问题"><!---->JDK1.7问题<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#与其他map区别" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="与其他Map区别"><!---->与其他Map区别<!----></a><ul class="sidebar-sub-headers"></ul></li></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#concurrenthashmap" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="ConcurrentHashMap"><!---->ConcurrentHashMap<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_1、介绍下concurrenthashmap" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="1、介绍下ConcurrentHashMap"><!---->1、介绍下ConcurrentHashMap<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_2、介绍下put方法-1-8" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="2、介绍下put方法（1.8）"><!---->2、介绍下put方法（1.8）<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_3、介绍下get方法-1-8" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="3、介绍下get方法（1.8）"><!---->3、介绍下get方法（1.8）<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_4、get中没有加锁的话-如何保证读到的数据不是脏数据呢" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="4、get中没有加锁的话，如何保证读到的数据不是脏数据呢？"><!---->4、get中没有加锁的话，如何保证读到的数据不是脏数据呢？<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_5、为什么concurrenthashmap中使用cas-synchronized" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="5、为什么concurrenthashmap中使用cas+synchronized？"><!---->5、为什么concurrenthashmap中使用cas+synchronized？<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_6、concurrenthashmap负载因子可以指定吗" class="router-link-active router-link-exact-active nav-link sidebar-link heading" aria-label="6、ConcurrentHashMap负载因子可以指定吗？"><!---->6、ConcurrentHashMap负载因子可以指定吗？<!----></a><ul class="sidebar-sub-headers"></ul></li></ul></li></ul><!--]--></li><li><!--[--><a href="/zh/interview/JUC.html" class="nav-link sidebar-link sidebar-page" aria-label="JUC"><span class="icon iconfont icon-lock" style=""></span>JUC<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/JVM.html" class="nav-link sidebar-link sidebar-page" aria-label="JVM"><span class="icon iconfont icon-lock" style=""></span>JVM<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/Linux.html" class="nav-link sidebar-link sidebar-page" aria-label="Linux"><span class="icon iconfont icon-lock" style=""></span>Linux<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/MySQL.html" class="nav-link sidebar-link sidebar-page" aria-label="MySQL"><span class="icon iconfont icon-lock" style=""></span>MySQL<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/NIO%E4%B8%8ENetty.html" class="nav-link sidebar-link sidebar-page" aria-label="Netty"><span class="icon iconfont icon-lock" style=""></span>Netty<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/Redis.html" class="nav-link sidebar-link sidebar-page" aria-label="Redis"><span class="icon iconfont icon-lock" style=""></span>Redis<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/%E4%B8%BB%E6%B5%81%E6%A1%86%E6%9E%B6.html" class="nav-link sidebar-link sidebar-page" aria-label="主流框架"><span class="icon iconfont icon-lock" style=""></span>主流框架<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/%E5%88%86%E5%B8%83%E5%BC%8F%E4%B8%8E%E9%AB%98%E6%80%A7%E8%83%BD%E9%AB%98%E5%8F%AF%E7%94%A8.html" class="nav-link sidebar-link sidebar-page" aria-label="分布式"><span class="icon iconfont icon-lock" style=""></span>分布式<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F.html" class="nav-link sidebar-link sidebar-page" aria-label="操作系统"><span class="icon iconfont icon-lock" style=""></span>操作系统<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/%E6%99%BA%E5%8A%9B%E9%A2%98.html" class="nav-link sidebar-link sidebar-page" aria-label="智力题"><span class="icon iconfont icon-lock" style=""></span>智力题<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1.html" class="nav-link sidebar-link sidebar-page" aria-label="系统设计"><span class="icon iconfont icon-lock" style=""></span>系统设计<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C.html" class="nav-link sidebar-link sidebar-page" aria-label="计算机网络"><span class="icon iconfont icon-lock" style=""></span>计算机网络<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/interview/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.html" class="nav-link sidebar-link sidebar-page" aria-label="设计模式"><!---->设计模式<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><p class="sidebar-heading clickable"><span class="icon iconfont icon-creative" style=""></span><a href="/zh/guide/" class="title">如何使用</a><!----></p><ul class="sidebar-links"><li><!--[--><a href="/zh/guide/page.html" class="nav-link sidebar-link sidebar-page" aria-label="页面配置"><span class="icon iconfont icon-page" style=""></span>页面配置<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/guide/markdown.html" class="nav-link sidebar-link sidebar-page" aria-label="Markdown 展示"><span class="icon iconfont icon-markdown" style=""></span>Markdown 展示<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/guide/disable.html" class="nav-link sidebar-link sidebar-page" aria-label="布局与功能禁用"><span class="icon iconfont icon-config" style=""></span>布局与功能禁用<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/guide/encrypt.html" class="nav-link sidebar-link sidebar-page" aria-label="密码加密的文章"><span class="icon iconfont icon-lock" style=""></span>密码加密的文章<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><p class="sidebar-heading"><span class="icon iconfont icon-note" style=""></span><span class="title">文章</span><!----></p><ul class="sidebar-links"><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><span class="icon iconfont icon-note" style=""></span><span class="title">文章 1-4</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><p class="sidebar-heading"><span class="icon iconfont icon-note" style=""></span><span class="title">文章 5-12</span><!----></p><ul class="sidebar-links"><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><span class="icon iconfont icon-note" style=""></span><span class="title">文章 5-8</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><p class="sidebar-heading"><span class="icon iconfont icon-note" style=""></span><span class="title">文章 9-12</span><!----></p><ul class="sidebar-links"><li><!--[--><a href="/zh/posts/article9.html" class="nav-link sidebar-link sidebar-page" aria-label="文章 9"><span class="icon iconfont icon-edit" style=""></span>文章 9<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/posts/article10.html" class="nav-link sidebar-link sidebar-page" aria-label="文章 10"><span class="icon iconfont icon-edit" style=""></span>文章 10<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/posts/article11.html" class="nav-link sidebar-link sidebar-page" aria-label="文章 11"><span class="icon iconfont icon-edit" style=""></span>文章 11<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/zh/posts/article12.html" class="nav-link sidebar-link sidebar-page" aria-label="文章 12"><span class="icon iconfont icon-edit" style=""></span>文章 12<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section><!--]--></li></ul></section><!--]--></li></ul></section><!--]--></li></ul><!--[--><!----><!--]--></aside><!--[--><main class="page" id="main-content"><!--[--><!----><nav class="breadcrumb disable"></nav><div class="page-title"><h1><span class="icon iconfont icon-lock" style=""></span>Java容器</h1><div class="page-info"><span class="author-info" aria-label="作者🖊" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon author-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="author icon"><path d="M649.6 633.6c86.4-48 147.2-144 147.2-249.6 0-160-128-288-288-288s-288 128-288 288c0 108.8 57.6 201.6 147.2 249.6-121.6 48-214.4 153.6-240 288-3.2 9.6 0 19.2 6.4 25.6 3.2 9.6 12.8 12.8 22.4 12.8h704c9.6 0 19.2-3.2 25.6-12.8 6.4-6.4 9.6-16 6.4-25.6-25.6-134.4-121.6-240-243.2-288z"></path></svg><span><a class="author-item" href="https://changlu.blog.csdn.net" target="_blank" rel="noopener noreferrer">长路</a></span><span property="author" content="长路"></span></span><!----><!----><span class="category-info" aria-label="分类🌈" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon category-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="category icon"><path d="M148.41 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H148.41c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.311-40.31zM147.556 553.478H429.73c22.263 0 40.311 18.048 40.311 40.31v282.176c0 22.263-18.048 40.312-40.31 40.312H147.555c-22.263 0-40.311-18.049-40.311-40.312V593.79c0-22.263 18.048-40.311 40.31-40.311zM593.927 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H593.927c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.31-40.31zM730.22 920.502H623.926c-40.925 0-74.22-33.388-74.22-74.425V623.992c0-41.038 33.387-74.424 74.425-74.424h222.085c41.038 0 74.424 33.226 74.424 74.067v114.233c0 10.244-8.304 18.548-18.547 18.548s-18.548-8.304-18.548-18.548V623.635c0-20.388-16.746-36.974-37.33-36.974H624.13c-20.585 0-37.331 16.747-37.331 37.33v222.086c0 20.585 16.654 37.331 37.126 37.331H730.22c10.243 0 18.547 8.304 18.547 18.547 0 10.244-8.304 18.547-18.547 18.547z"></path></svg><ul class="categories-wrapper"><li class="category category8 clickable" role="navigation">面试题</li><meta property="articleSection" content="面试题"></ul></span><span aria-label="标签🏷" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon tag-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="tag icon"><path d="M939.902 458.563L910.17 144.567c-1.507-16.272-14.465-29.13-30.737-30.737L565.438 84.098h-.402c-3.215 0-5.726 1.005-7.634 2.913l-470.39 470.39a10.004 10.004 0 000 14.164l365.423 365.424c1.909 1.908 4.42 2.913 7.132 2.913s5.223-1.005 7.132-2.913l470.39-470.39c2.01-2.11 3.014-5.023 2.813-8.036zm-240.067-72.121c-35.458 0-64.286-28.828-64.286-64.286s28.828-64.285 64.286-64.285 64.286 28.828 64.286 64.285-28.829 64.286-64.286 64.286z"></path></svg><ul class="tags-wrapper"><li class="tag tag6 clickable" role="navigation">Java容器</li></ul><meta property="keywords" content="Java容器"></span><span class="reading-time-info" aria-label="阅读时间⌛" data-balloon-pos="down" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon timer-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="timer icon"><path d="M799.387 122.15c4.402-2.978 7.38-7.897 7.38-13.463v-1.165c0-8.933-7.38-16.312-16.312-16.312H256.33c-8.933 0-16.311 7.38-16.311 16.312v1.165c0 5.825 2.977 10.874 7.637 13.592 4.143 194.44 97.22 354.963 220.201 392.763-122.204 37.542-214.893 196.511-220.2 389.397-4.661 5.049-7.638 11.651-7.638 19.03v5.825h566.49v-5.825c0-7.379-2.849-13.981-7.509-18.9-5.049-193.016-97.867-351.985-220.2-389.527 123.24-37.67 216.446-198.453 220.588-392.892zM531.16 450.445v352.632c117.674 1.553 211.787 40.778 211.787 88.676H304.097c0-48.286 95.149-87.382 213.728-88.676V450.445c-93.077-3.107-167.901-81.297-167.901-177.093 0-8.803 6.99-15.793 15.793-15.793 8.803 0 15.794 6.99 15.794 15.793 0 80.261 63.69 145.635 142.01 145.635s142.011-65.374 142.011-145.635c0-8.803 6.99-15.793 15.794-15.793s15.793 6.99 15.793 15.793c0 95.019-73.789 172.82-165.96 177.093z"></path></svg><span>大约 32 分钟</span><meta property="timeRequired" content="PT32M"></span></div><hr></div><div class="toc-place-holder"><aside id="toc"><div class="toc-header">此页内容</div><div class="toc-wrapper"><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_1、java的集合有哪些" class="router-link-active router-link-exact-active toc-link level2">1、Java的集合有哪些？</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_2、说说-list-set-queue-map-四者的区别" class="router-link-active router-link-exact-active toc-link level2">2、说说 List, Set, Queue, Map 四者的区别？</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_3、集合框架底层数据结构总结" class="router-link-active router-link-exact-active toc-link level2">3、集合框架底层数据结构总结</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_4、如何选用集合" class="router-link-active router-link-exact-active toc-link level2">4、如何选用集合？</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_5、为什么要使用集合" class="router-link-active router-link-exact-active toc-link level2">5、为什么要使用集合？</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#collection-子接口之-list" class="router-link-active router-link-exact-active toc-link level2">Collection 子接口之 List</a></li><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#arrarylist" class="router-link-active router-link-exact-active toc-link level3">ArraryList</a></li><!----><!--]--></ul><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#collection-子接口之-set" class="router-link-active router-link-exact-active toc-link level2">Collection 子接口之 Set</a></li><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_1、comparable-和-comparator-的区别" class="router-link-active router-link-exact-active toc-link level3">1、comparable 和 Comparator 的区别</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_2、无序性和不可重复性的含义是什么" class="router-link-active router-link-exact-active toc-link level3">2、无序性和不可重复性的含义是什么</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_3、比较-hashset、linkedhashset-和-treeset-三者的异同" class="router-link-active router-link-exact-active toc-link level3">3、比较 HashSet、LinkedHashSet 和 TreeSet 三者的异同</a></li><!----><!--]--></ul><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#collection-子接口之-queue" class="router-link-active router-link-exact-active toc-link level2">Collection 子接口之 Queue</a></li><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_1、queue-与-deque-的区别" class="router-link-active router-link-exact-active toc-link level3">1、Queue 与 Deque 的区别</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_2、arraydeque-与-linkedlist-的区别" class="router-link-active router-link-exact-active toc-link level3">2、ArrayDeque 与 LinkedList 的区别</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_3、说一说-priorityqueue" class="router-link-active router-link-exact-active toc-link level3">3、说一说 PriorityQueue</a></li><!----><!--]--></ul><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#hashmap" class="router-link-active router-link-exact-active toc-link level2">HashMap</a></li><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_1、hashmap的原理-内部的数据结构" class="router-link-active router-link-exact-active toc-link level3">1、HashMap的原理，内部的数据结构</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_2、put-方法讲一下" class="router-link-active router-link-exact-active toc-link level3">2、put()方法讲一下</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_3、hashmap中hash函数怎么是实现的" class="router-link-active router-link-exact-active toc-link level3">3、HashMap中hash函数怎么是实现的?</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_4、为什么hashmap中的-位数必须为奇数-length-1" class="router-link-active router-link-exact-active toc-link level3">4、为什么HashMap中的&amp;位数必须为奇数（Length-1）</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_5、常见的哈希函数以及哈希碰撞解决方案" class="router-link-active router-link-exact-active toc-link level3">5、常见的哈希函数以及哈希碰撞解决方案</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_6、红黑树的特点" class="router-link-active router-link-exact-active toc-link level3">6、红黑树的特点</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_7、不使用锁如何改造hashmap使其线程安全-redis" class="router-link-active router-link-exact-active toc-link level3">7、不使用锁如何改造Hashmap使其线程安全（redis）</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#hashset" class="router-link-active router-link-exact-active toc-link level3">HashSet</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#容量、扩容问题" class="router-link-active router-link-exact-active toc-link level3">容量、扩容问题</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#jdk1-7问题" class="router-link-active router-link-exact-active toc-link level3">JDK1.7问题</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#与其他map区别" class="router-link-active router-link-exact-active toc-link level3">与其他Map区别</a></li><!----><!--]--></ul><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#concurrenthashmap" class="router-link-active router-link-exact-active toc-link level2">ConcurrentHashMap</a></li><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_1、介绍下concurrenthashmap" class="router-link-active router-link-exact-active toc-link level3">1、介绍下ConcurrentHashMap</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_2、介绍下put方法-1-8" class="router-link-active router-link-exact-active toc-link level3">2、介绍下put方法（1.8）</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_3、介绍下get方法-1-8" class="router-link-active router-link-exact-active toc-link level3">3、介绍下get方法（1.8）</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_4、get中没有加锁的话-如何保证读到的数据不是脏数据呢" class="router-link-active router-link-exact-active toc-link level3">4、get中没有加锁的话，如何保证读到的数据不是脏数据呢？</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_5、为什么concurrenthashmap中使用cas-synchronized" class="router-link-active router-link-exact-active toc-link level3">5、为什么concurrenthashmap中使用cas+synchronized？</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/zh/interview/Java%E5%AE%B9%E5%99%A8.html#_6、concurrenthashmap负载因子可以指定吗" class="router-link-active router-link-exact-active toc-link level3">6、ConcurrentHashMap负载因子可以指定吗？</a></li><!----><!--]--></ul><!--]--></ul></div></aside></div><!----><div class="theme-hope-content"><h1 id="java容器" tabindex="-1"><a class="header-anchor" href="#java容器" aria-hidden="true">#</a> Java容器</h1><h2 id="_1、java的集合有哪些" tabindex="-1"><a class="header-anchor" href="#_1、java的集合有哪些" aria-hidden="true">#</a> 1、Java的集合有哪些？</h2><p>一个是Collection接口，另一个是Map接口。</p><ul><li>Collection接口：实现包含Set、List、Queue。</li><li>Map：HashMap、HashTable、SortedMap。</li></ul><p><img src="https://pictured-bed.oss-cn-beijing.aliyuncs.com/img/2022/6/202206151624872.png" alt="image-20220615162458801" loading="lazy"></p><h2 id="_2、说说-list-set-queue-map-四者的区别" tabindex="-1"><a class="header-anchor" href="#_2、说说-list-set-queue-map-四者的区别" aria-hidden="true">#</a> 2、说说 List, Set, Queue, Map 四者的区别？</h2><p><code>List</code>(对付顺序的好帮手): 存储的元素是有序的、可重复的。</p><p><code>Set</code>(注重独一无二的性质): 存储的元素是无序的、不可重复的。</p><p><code>Queue</code>(实现排队功能的叫号机): 按特定的排队规则来确定先后顺序，存储的元素是有序的、可重复的。</p><p><code>Map</code>(用 key 来搜索的专家): 使用键值对（key-value）存储，类似于数学上的函数 y=f(x)，&quot;x&quot; 代表 key，&quot;y&quot; 代表 value，key 是无序的、不可重复的，value 是无序的、可重复的，每个键最多映射到一个值。</p><h2 id="_3、集合框架底层数据结构总结" tabindex="-1"><a class="header-anchor" href="#_3、集合框架底层数据结构总结" aria-hidden="true">#</a> 3、集合框架底层数据结构总结</h2><p>List</p><ul><li><code>Arraylist</code>： <code>Object[]</code> 数组</li><li><code>Vector</code>：<code>Object[]</code> 数组</li><li><code>LinkedList</code>： 双向链表(JDK1.6 之前为循环链表，JDK1.7 取消了循环)</li></ul><p>Set</p><ul><li><code>HashSet</code>(无序，唯一): 基于 <code>HashMap</code> 实现的，底层采用 <code>HashMap</code> 来保存元素</li><li><code>LinkedHashSet</code>: <code>LinkedHashSet</code> 是 <code>HashSet</code> 的子类，并且其内部是通过 <code>LinkedHashMap</code> 来实现的。有点类似于我们之前说的 <code>LinkedHashMap</code> 其内部是基于 <code>HashMap</code> 实现一样，不过还是有一点点区别的</li><li><code>TreeSet</code>(有序，唯一): 红黑树(自平衡的排序二叉树</li></ul><p>Queue</p><ul><li><code>PriorityQueue</code>: <code>Object[]</code> 数组来实现二叉堆</li><li><code>ArrayQueue</code>: <code>Object[]</code> 数组 + 双指针</li></ul><p>Map</p><ul><li><code>HashMap</code>： JDK1.8 之前 <code>HashMap</code> 由数组+链表组成的，数组是 <code>HashMap</code> 的主体，链表则是主要为了解决哈希冲突而存在的（“拉链法”解决冲突）。JDK1.8 以后在解决哈希冲突时有了较大的变化，当链表长度大于阈值（默认为 8）（将链表转换成红黑树前会判断，如果当前数组的长度小于 64，那么会选择先进行数组扩容，而不是转换为红黑树）时，将链表转化为红黑树，以减少搜索时间</li><li><code>LinkedHashMap</code>： <code>LinkedHashMap</code> 继承自 <code>HashMap</code>，所以它的底层仍然是基于拉链式散列结构即由<strong>数组和链表或红黑树</strong>组成。另外，<code>LinkedHashMap</code> 在上面结构的基础上，增加了一条双向链表，使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作，实现了访问顺序相关逻辑。详细可以查看：<a href="https://www.imooc.com/article/22931" target="_blank" rel="noopener noreferrer">《LinkedHashMap 源码详细分析（JDK1.8）》open in new window<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></li><li><code>Hashtable</code>： 数组+链表组成的，数组是 <code>Hashtable</code> 的主体，链表则是主要为了解决哈希冲突而存在的</li><li><code>TreeMap</code>： 红黑树（自平衡的排序二叉树）</li></ul><h2 id="_4、如何选用集合" tabindex="-1"><a class="header-anchor" href="#_4、如何选用集合" aria-hidden="true">#</a> 4、如何选用集合？</h2><p>比如我们需要根据<strong>键值</strong>获取到元素值时就选用 <code>Map</code> 接口下的集合，需要排序时选择 <code>TreeMap</code>,不需要排序时就选择 <code>HashMap</code>,需要保证线程安全就选用 <code>ConcurrentHashMap</code>。</p><p>当我们只需要<strong>存放元素值</strong>时，就选择实现<code>Collection</code> 接口的集合，需要保证元素唯一时选择实现 <code>Set</code> 接口的集合比如 <code>TreeSet</code> 或 <code>HashSet</code>，不需要就选择实现 <code>List</code> 接口的比如 <code>ArrayList</code> 或 <code>LinkedList</code>，然后再根据实现这些接口的集合的特点来选用。</p><h2 id="_5、为什么要使用集合" tabindex="-1"><a class="header-anchor" href="#_5、为什么要使用集合" aria-hidden="true">#</a> 5、为什么要使用集合？</h2><p>一般的话我们要存储一组数据通常会使用数组来进行存储，不过自己使用数组的话存在一些弊端，例如数组扩容问题，还有就是数据的类型是多种多样的，单单使用数组无法得到满足，并且可能会出现重复造轮子的问题。</p><p>使用集合提高了数据存储的灵活性，Java 集合不仅可以用来存储不同类型不同数量的对象，还可以保存具有映射关系的数据。</p><h2 id="collection-子接口之-list" tabindex="-1"><a class="header-anchor" href="#collection-子接口之-list" aria-hidden="true">#</a> Collection 子接口之 List</h2><h3 id="arrarylist" tabindex="-1"><a class="header-anchor" href="#arrarylist" aria-hidden="true">#</a> ArraryList</h3><h4 id="_1、arraylist-和-vector-的区别" tabindex="-1"><a class="header-anchor" href="#_1、arraylist-和-vector-的区别" aria-hidden="true">#</a> 1、Arraylist 和 Vector 的区别?</h4><p>底层都是使用object[]来存储的，唯一区别就是一个是线程安全的，另一个是线程不安全的。</p><h4 id="_2、arrarylist与linkedlist区别" tabindex="-1"><a class="header-anchor" href="#_2、arrarylist与linkedlist区别" aria-hidden="true">#</a> 2、ArraryList与LinkedList区别</h4><p>1、<strong>是否保证线程安全</strong>： ArrayList 和 LinkedList 都是不同步的，也就是不保证线程安全；</p><p>2、<strong>底层数据结构</strong>： Arraylist 底层使用的是 Object 数组；LinkedList 底层使用的是 双向链表 数据结构（JDK1.6 之前为循环链表，JDK1.7 取消了循环。注意双向链表和双向循环链表的区别，下面有介绍到！）</p><p>3、<strong>插入和删除是否受元素位置的影响</strong>：</p><ul><li>ArraryList：执行add(E e)时间复杂度为O(1)、执行add(int index, E element)时间复杂度为O(n-1)</li><li>LinkedList：头插、尾插时间复杂度为O(1)，如果是要在指定位置 <code>i</code> 插入和删除元素的话（<code>add(int index, E element)</code>，<code>remove(Object o)</code>）， 时间复杂度为 O(n) ，因为需要先移动到指定位置再插入（中间有一个移动过程）。</li></ul><p>4、<strong>是否支持快速随机访问</strong>： <code>ArrayList</code> 支持，<code>LinkedList</code> 不支持高效的随机元素访问。</p><p>5、<strong>内存空间占用</strong>：对于ArraryList需要在开辟时预留一部分空间；而LinkedList在存储每个元素时需要多一部分空间，因为还包含了前后指向指针。</p><h4 id="_3、arrarylist的扩容机制" tabindex="-1"><a class="header-anchor" href="#_3、arrarylist的扩容机制" aria-hidden="true">#</a> 3、ArraryList的扩容机制</h4><p>有空构造器与非空构造器：若是使用空构造器或者非空构造器(n=0)，赋值的就只是一个空数组；对于非空构造器n&gt;0，则是进行分配空间。</p><p>在add()添加元素会进行容量控制，保证容量满足情况下会进行添加元素。</p><p>扩容：扩容的容量是自身容量+自身容量的一半，也就是1.5倍。</p><h2 id="collection-子接口之-set" tabindex="-1"><a class="header-anchor" href="#collection-子接口之-set" aria-hidden="true">#</a> Collection 子接口之 Set</h2><h3 id="_1、comparable-和-comparator-的区别" tabindex="-1"><a class="header-anchor" href="#_1、comparable-和-comparator-的区别" aria-hidden="true">#</a> 1、comparable 和 Comparator 的区别</h3><p><code>comparable</code> 接口实际上是出自<code>java.lang</code>包 它有一个 <code>compareTo(Object obj)</code>方法用来排序</p><ul><li>某个类去实现接口的。</li></ul><p><code>comparator</code>接口实际上是出自 java.util 包它有一个<code>compare(Object obj1, Object obj2)</code>方法用来排序</p><ul><li>使用两个参数版的 `Collections.sort()</li></ul><h3 id="_2、无序性和不可重复性的含义是什么" tabindex="-1"><a class="header-anchor" href="#_2、无序性和不可重复性的含义是什么" aria-hidden="true">#</a> 2、无序性和不可重复性的含义是什么</h3><p>1、什么是无序性？无序性不等于随机性 ，无序性是指存储的数据在底层数组中<strong>并非按照数组索引的顺序添加</strong> ，而是根据数据的哈希值决定的。</p><p>2、什么是不可重复性？不可重复性是指添加的元素按照 equals()判断时 ，返回 false，需要同时重写 equals()方法和 HashCode()方法。</p><h3 id="_3、比较-hashset、linkedhashset-和-treeset-三者的异同" tabindex="-1"><a class="header-anchor" href="#_3、比较-hashset、linkedhashset-和-treeset-三者的异同" aria-hidden="true">#</a> 3、比较 HashSet、LinkedHashSet 和 TreeSet 三者的异同</h3><p><code>HashSet</code>、<code>LinkedHashSet</code> 和 <code>TreeSet</code> 都是 <code>Set</code> 接口的实现类，都能保证元素唯一，并且都不是线程安全的。</p><p><code>HashSet</code>、<code>LinkedHashSet</code> 和 <code>TreeSet</code> 的主要区别在于底层数据结构不同。</p><ul><li><code>HashSet</code> 的底层数据结构是<strong>哈希表</strong>（基于 <code>HashMap</code> 实现）。</li><li><code>LinkedHashSet</code> 的底层数据结构是<strong>链表和哈希表</strong>，元素的插入和取出顺序满足 FIFO。</li><li><code>TreeSet</code> 底层数据结构是<strong>红黑树</strong>，元素是有序的，排序的方式有自然排序和定制排序。</li></ul><p>底层数据结构不同又导致这三者的应用场景不同。<code>HashSet</code> 用于不需要保证元素插入和取出顺序的场景，<code>LinkedHashSet</code> 用于保证元素的插入和取出顺序满足 FIFO 的场景，<code>TreeSet</code> 用于支持对元素自定义排序规则的场景。</p><h2 id="collection-子接口之-queue" tabindex="-1"><a class="header-anchor" href="#collection-子接口之-queue" aria-hidden="true">#</a> Collection 子接口之 Queue</h2><h3 id="_1、queue-与-deque-的区别" tabindex="-1"><a class="header-anchor" href="#_1、queue-与-deque-的区别" aria-hidden="true">#</a> 1、Queue 与 Deque 的区别</h3><p><code>Queue</code> 是单端队列，只能从一端插入元素，另一端删除元素，实现上一般遵循 <strong>先进先出（FIFO）</strong> 规则</p><p><code>Deque</code> 是双端队列，在队列的两端均可以插入或删除元素。</p><ul><li>事实上，<code>Deque</code> 还提供有 <code>push()</code> 和 <code>pop()</code> 等其他方法，可用于模拟栈。</li></ul><h3 id="_2、arraydeque-与-linkedlist-的区别" tabindex="-1"><a class="header-anchor" href="#_2、arraydeque-与-linkedlist-的区别" aria-hidden="true">#</a> 2、ArrayDeque 与 LinkedList 的区别</h3><p><code>ArrayDeque</code> 和 <code>LinkedList</code> 都实现了 <code>Deque</code> 接口，两者都具有队列的功能，但两者有什么区别呢？</p><ul><li><code>ArrayDeque</code> 是基于<strong>可变长的数组和双指针</strong>来实现，而 <code>LinkedList</code> 则通过<strong>链表</strong>来实现。</li><li><code>ArrayDeque</code> 不支持存储 <code>NULL</code> 数据，但 <code>LinkedList</code> 支持。</li><li><code>ArrayDeque</code> 是在 JDK1.6 才被引入的，而<code>LinkedList</code> 早在 JDK1.2 时就已经存在。</li><li><code>ArrayDeque</code> 插入时可能存在扩容过程, 不过均摊后的插入操作依然为 O(1)。虽然 <code>LinkedList</code> 不需要扩容，但是每次插入数据时均需要申请新的堆空间，均摊性能相比更慢。</li></ul><p>从性能的角度上，选用 <code>ArrayDeque</code> 来实现队列要比 <code>LinkedList</code> 更好。此外，<code>ArrayDeque</code> 也可以用于实现栈。</p><h3 id="_3、说一说-priorityqueue" tabindex="-1"><a class="header-anchor" href="#_3、说一说-priorityqueue" aria-hidden="true">#</a> 3、说一说 PriorityQueue</h3><p><code>PriorityQueue</code> 是在 JDK1.5 中被引入的, 其与 <code>Queue</code> 的区别在于元素<strong>出队顺序是与优先级相关</strong>的，即总是优先级最高的元素先出队。</p><p><strong>特点</strong>：</p><p>1、<code>PriorityQueue</code> 是<strong>非线程安全</strong>的，且不支持存储 <code>NULL</code> 和 <code>non-comparable</code> 的对象。</p><p>2、默认是小顶堆，但可以接收一个 <code>Comparator</code> 作为构造参数，从而来自定义元素优先级的先后。</p><p>3、利用了二叉堆的数据结构来实现的，底层使用可变长的数组来存储数据。</p><p>4、通过堆元素的上浮和下沉，实现了在 O(logn) 的时间复杂度内插入元素和删除堆顶元素。</p><h2 id="hashmap" tabindex="-1"><a class="header-anchor" href="#hashmap" aria-hidden="true">#</a> HashMap</h2><h3 id="_1、hashmap的原理-内部的数据结构" tabindex="-1"><a class="header-anchor" href="#_1、hashmap的原理-内部的数据结构" aria-hidden="true">#</a> 1、HashMap的原理，内部的数据结构</h3><p>底层是数组+链表，在jdk1.8后又引入了红黑树(红黑树转换时机是在当前某个bucket链表长度&gt;8，且数组长度&gt;=64，就会经历依次转换红黑树的过程；时间复杂度由O(n)转为O(logn))。</p><p>实例化：会创建一个长度为Capacity的Node数组(Node实现Entry接口，Node中有key、value键值对)，只有当put时才会分配空间默认是16，扩容为2倍。</p><p>Hash查询效率为O(1)。</p><p>链表查询效率为O(n)。</p><p>红黑树查询效率为O(logn)。</p><h3 id="_2、put-方法讲一下" tabindex="-1"><a class="header-anchor" href="#_2、put-方法讲一下" aria-hidden="true">#</a> 2、put()方法讲一下</h3><p><img src="https://pictured-bed.oss-cn-beijing.aliyuncs.com/img/2022/6/202206151553452.jpeg" alt="img" loading="lazy"></p><h3 id="_3、hashmap中hash函数怎么是实现的" tabindex="-1"><a class="header-anchor" href="#_3、hashmap中hash函数怎么是实现的" aria-hidden="true">#</a> 3、HashMap中hash函数怎么是实现的?</h3><blockquote><p><a href="https://blog.csdn.net/qq_29066329/article/details/90743216" target="_blank" rel="noopener noreferrer">HashMap中hash函数怎么是实现的?<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>、</p></blockquote><p>源码：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token function">hash</span><span class="token punctuation">(</span><span class="token class-name">Object</span> key<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">int</span> h<span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>key <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token number">0</span> <span class="token operator">:</span> <span class="token punctuation">(</span>h <span class="token operator">=</span> key<span class="token punctuation">.</span><span class="token function">hashCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">^</span> <span class="token punctuation">(</span>h <span class="token operator">&gt;&gt;&gt;</span> <span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>


<span class="token comment">//上面可拆为</span>
<span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token function">hash</span><span class="token punctuation">(</span><span class="token class-name">Object</span> key<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>key <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">int</span> h<span class="token punctuation">;</span>
    h <span class="token operator">=</span> key<span class="token punctuation">.</span><span class="token function">hashCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span>；返回散列值也就是hashcode
    <span class="token comment">// ^ ：按位异或</span>
    <span class="token comment">// &gt;&gt;&gt;:无符号右移，忽略符号位，空位都以0补齐</span>
    <span class="token comment">//其中n是数组的长度，即Map的数组部分初始化长度</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>h <span class="token operator">^</span> <span class="token punctuation">(</span>h <span class="token operator">&gt;&gt;&gt;</span> <span class="token number">16</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">//最终hash地址为：(n-1) &amp; hash(key)</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>HashMap的hash()实际上就是<strong>扰动函数</strong>：实际上就是对key求hash值，接着对该hash值得高16bit以及低16bit进行异化。</p><ul><li>目的：混合了原hash值得高位与低位，增大随机性，让数据元素更加均衡的散列分布，减少碰撞，最终来让数据的存放和获取效果更好。</li></ul><blockquote><p>理论</p></blockquote><p>实现方式：(key == null) ? 0 : (h = key.hashCode()) ^ (h &gt;&gt;&gt; 16)。在取得哈希值之后还有&amp;当前的数组长度，用来限制范围。</p><p>实际上该hash()方法就是扰动函数，其做的操作就是将key的hash值得高阶16位与低阶十六位进行异或。</p><p>目的：混合原来hash值得高位与低位，增加随机性，最终能让数据元素更加均衡的散列分布，以<strong>达到减少碰撞的目的</strong>，最终让存储与取得值得效果更好。</p><p>方式：随机数法(取关键字中的随机值作为散列地址)、除留余数法(取关键字被某个&lt;=n的数字来进行除余取得散列地址)、建立公共溢出区。</p><p>注意：HashMap对于哈希冲突采用的是链地址法。</p><h3 id="_4、为什么hashmap中的-位数必须为奇数-length-1" tabindex="-1"><a class="header-anchor" href="#_4、为什么hashmap中的-位数必须为奇数-length-1" aria-hidden="true">#</a> 4、为什么HashMap中的&amp;位数必须为奇数（Length-1）</h3><p>进行&amp;实际上是进行计算索引下标：</p><p><img src="https://pictured-bed.oss-cn-beijing.aliyuncs.com/img/2022/6/202206151805850.png" alt="image-20220615180557809" loading="lazy"></p><p>默认初始化的容量一定是为2的次方或者16，当偶数-1是为奇数，在奇数情况中所有二进制位数为1，在这种情况，通过扰乱函数求得的hash值再进行&amp;实际上就相当于进行了求模，比%更快。</p><ul><li>为什么要取模？是因为要得到在指定容量范围中的哈希索引值。</li><li>为了让取模效率更高我们则使用&amp;运算符，而对于使用&amp;运算符，那么另一个二进制位应当全为1也就是奇数才会有&amp;的效果。</li></ul><p>最终实际上就可以引入我们在初始化时，为什么要对我们初始的容量进行控制的原因了。</p><blockquote><p>简述</p></blockquote><p>因为我们通过扰乱函数hash()得到的一个hash值是一定会大于数组的容量，那么想要计算得到对应范围中的索引下标，那么就需要进行%运算。</p><p>而由于%运算相对效率不高，在hashmap中则是使用的&amp;运算来进行求模，若是想要使用&amp;来求模，那么对应的容量范围必须是一个奇数。<strong>引申初始化容量</strong></p><p>简而言之就是<strong>通过使用&amp;来代替%运算，提高运算效率</strong>。</p><h3 id="_5、常见的哈希函数以及哈希碰撞解决方案" tabindex="-1"><a class="header-anchor" href="#_5、常见的哈希函数以及哈希碰撞解决方案" aria-hidden="true">#</a> 5、常见的哈希函数以及哈希碰撞解决方案</h3><p><strong>哈希函数</strong>如下：</p><p>直接定址法：直接以关键字k或者k加上某个常数（k+c）作为哈希地址。</p><p>数字分析法：提取关键字中取值比较均匀的数字作为哈希地址。</p><p>除留余数法：用关键字k除以某个不大于哈希表长度m的数p，将所得余数作为哈希表地址。</p><p>分段叠加法：按照哈希表地址位数将关键字分成位数相等的几部分，其中最后一部分可以比较短。然后将这几部分相加，舍弃最高进位后的结果就是该关键字的哈希地址。</p><p>平方取中法：如果关键字各个部分分布都不均匀的话，可以先求出它的平方值，然后按照需求取中间的几位作为哈希地址。</p><p>伪随机数法：采用一个伪随机数当作哈希函数。</p><p><strong>常用的解决方案</strong>：</p><ul><li>开放定址法：开放定址法就是一旦发生了冲突，就去寻找下一个空的散列地址，只要散列表足够大，空的散列地址总能找到，并将记录存入。</li><li>链地址法（HashMap中采取）：将哈希表的每个单元作为链表的头结点，所有哈希地址为i的元素构成一个同义词链表。即发生冲突时就把该关键字链在以该单元为头结点的链表的尾部。</li><li>再哈希法：当哈希地址发生冲突用其他的函数计算另一个哈希函数地址，直到冲突不再产生为止。</li><li>建立公共溢出区：将哈希表分为基本表和溢出表两部分，发生冲突的元素都放入溢出表中。</li></ul><h3 id="_6、红黑树的特点" tabindex="-1"><a class="header-anchor" href="#_6、红黑树的特点" aria-hidden="true">#</a> 6、红黑树的特点</h3><p>1、根节点是黑色的，叶子结点也是黑色的。</p><p>2、一个红色节点的左右结点都是黑色的。</p><p>3、每个结点不是红色就是黑色。</p><p>4、从叶子结点到根节点过程中黑色结点的数量一致，也就是具有相同的黑色高度。</p><p>特点：让树尽可能平衡，缩减查询的时间复杂度。</p><h3 id="_7、不使用锁如何改造hashmap使其线程安全-redis" tabindex="-1"><a class="header-anchor" href="#_7、不使用锁如何改造hashmap使其线程安全-redis" aria-hidden="true">#</a> 7、不使用锁如何改造Hashmap使其线程安全（redis）</h3><blockquote><p><a href="https://blog.csdn.net/weixin_43374578/article/details/123479567" target="_blank" rel="noopener noreferrer">Redis分布式锁<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></p></blockquote><p>使用setnx，并且要考虑到宕机情况，设置一个失效时间。</p><h3 id="hashset" tabindex="-1"><a class="header-anchor" href="#hashset" aria-hidden="true">#</a> HashSet</h3><h4 id="_1、hashset介绍" tabindex="-1"><a class="header-anchor" href="#_1、hashset介绍" aria-hidden="true">#</a> 1、HashSet介绍</h4><p>本质上还是一个HashMap，在HashSet中就维护一个HashMap，在每次add添加的时候，将对应的值作为key来进行插入，对应value则是一个Object对象，没多大意义，大量复用了HashMap的方法。</p><h3 id="容量、扩容问题" tabindex="-1"><a class="header-anchor" href="#容量、扩容问题" aria-hidden="true">#</a> 容量、扩容问题</h3><h4 id="_1、初始化容量以及负载因子" tabindex="-1"><a class="header-anchor" href="#_1、初始化容量以及负载因子" aria-hidden="true">#</a> 1、初始化容量以及负载因子</h4><blockquote><p>初始化容量：初始化计算阈值</p></blockquote><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token class-name">HashMap</span><span class="token punctuation">(</span><span class="token keyword">int</span> initialCapacity<span class="token punctuation">,</span> <span class="token keyword">float</span> loadFactor<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">//校验一个阈值范围</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>initialCapacity <span class="token operator">&gt;</span> MAXIMUM_CAPACITY<span class="token punctuation">)</span>
        initialCapacity <span class="token operator">=</span> MAXIMUM_CAPACITY<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>loadFactor <span class="token operator">=</span> loadFactor<span class="token punctuation">;</span><span class="token comment">//设置默认的加载因子</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>threshold <span class="token operator">=</span> <span class="token function">tableSizeFor</span><span class="token punctuation">(</span>initialCapacity<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//计算最适合的存储容量</span>
<span class="token punctuation">}</span>

<span class="token comment">//得到2的倍数最小值</span>
<span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token function">tableSizeFor</span><span class="token punctuation">(</span><span class="token keyword">int</span> cap<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">int</span> n <span class="token operator">=</span> cap <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
    n <span class="token operator">|=</span> n <span class="token operator">&gt;&gt;&gt;</span> <span class="token number">1</span><span class="token punctuation">;</span>
    n <span class="token operator">|=</span> n <span class="token operator">&gt;&gt;&gt;</span> <span class="token number">2</span><span class="token punctuation">;</span>
    n <span class="token operator">|=</span> n <span class="token operator">&gt;&gt;&gt;</span> <span class="token number">4</span><span class="token punctuation">;</span>
    n <span class="token operator">|=</span> n <span class="token operator">&gt;&gt;&gt;</span> <span class="token number">8</span><span class="token punctuation">;</span>
    n <span class="token operator">|=</span> n <span class="token operator">&gt;&gt;&gt;</span> <span class="token number">16</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>n <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token number">1</span> <span class="token operator">:</span> <span class="token punctuation">(</span>n <span class="token operator">&gt;=</span> MAXIMUM_CAPACITY<span class="token punctuation">)</span> <span class="token operator">?</span> MAXIMUM_CAPACITY <span class="token operator">:</span> n <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>若是我们自己输入17，那么此时2的倍数最小值就是n则为31，返回的时候+1即为一个偶数（也就是2的倍数）；若是16也是最终返回16；</p><p><img src="https://pictured-bed.oss-cn-beijing.aliyuncs.com/img/2022/6/202206151553484.png" alt="image-20220419162043035" loading="lazy"></p><p><strong>结论</strong>：取得临近17最小的二的倍数的一个二进制数，最终返回得到的值一定是一个2的倍数。</p><blockquote><p>负载因子</p></blockquote><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">//默认的负载因子</span>
<span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">float</span> DEFAULT_LOAD_FACTOR <span class="token operator">=</span> <span class="token number">0.75f</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div></div></div><p>核心用途：主要决定之后<strong>数据量达到多少会进行扩容，来减少Hash碰撞</strong>。</p><p>并不说你数据量大就一定能够将hashmap中的位置全部占满，某些小位置可能出现大量的碰撞，此时就失去了Map数组的性能。那么正因如此选择一个合理的大小来进行扩容很关键，对于0.75来说也就是一旦阈值容量占了3/4时就需要进行扩容了，来减少Hash碰撞。</p><p>扩展：若是你想用更多的空间来换取时间的话，那么可以把负载因子调小。</p><blockquote><p>简述</p></blockquote><p>初始化容量：初始化的容量大小为传入临近传入容量的最小的二的倍数的二进制数值+1，也就是2的倍数。如17就会得到32，16得到16。</p><p>加载因子：其与HashMap的扩容相关，默认加载因子是0.75，也就是说当数组中的容量&gt;=四分之三时就会进行扩容。<strong>引出扩容元素拆分。</strong></p><h4 id="_2、扩容元素拆分" tabindex="-1"><a class="header-anchor" href="#_2、扩容元素拆分" aria-hidden="true">#</a> 2、扩容元素拆分</h4><p>背景：若是当前数组长度不足了，那么就会对数组进行扩容，此时就需要将原本数组中的元素拆分到新的数组当中去，那么该如何进行迁移呢？</p><ul><li>jdk1.7中的做法就是重新计算元素的hash，并且进行迁移。</li><li>jdk1.8中十分巧妙，不再需要重新计算，而是使用原来<code>该元素的hash值 &amp; (扩容新增的长度)</code>，若是=0那么位置不变，若是=1那么新的位置就加上扩容新增的长度。</li></ul><p>JDK8的好处：不需要再计算每个数组中元素的哈希值了。</p><p><img src="https://pictured-bed.oss-cn-beijing.aliyuncs.com/img/2022/6/202206151553602.png" alt="image-20220419164937830" loading="lazy"></p><h3 id="jdk1-7问题" tabindex="-1"><a class="header-anchor" href="#jdk1-7问题" aria-hidden="true">#</a> JDK1.7问题</h3><h4 id="_1、jdk1-7为什么使用头插法" tabindex="-1"><a class="header-anchor" href="#_1、jdk1-7为什么使用头插法" aria-hidden="true">#</a> 1、JDK1.7为什么使用头插法？</h4><p>对于插入的时间效率上并没有与尾插法有什么提高，主要应该是因为局部性原理，新插入的数据有较高的几率会先被查询。</p><h4 id="_2、hashmap1-7-key为null存放在什么位置" tabindex="-1"><a class="header-anchor" href="#_2、hashmap1-7-key为null存放在什么位置" aria-hidden="true">#</a> 2、HashMap1.7 Key为null存放在什么位置</h4><p>上来会有putForNullKey()方法，会尝试在table[0]的表头插入，若是table[0]链表中找到key为null的就赋值给这个元素value，若是没有找到，就添加到table[0]的表头。</p><h4 id="_3、扩容元素拆分如何拆分-jdk1-7与8有啥区别" tabindex="-1"><a class="header-anchor" href="#_3、扩容元素拆分如何拆分-jdk1-7与8有啥区别" aria-hidden="true">#</a> 3、扩容元素拆分如何拆分，JDK1.7与8有啥区别？</h4><p>当容量到达对应的加载因子就会进行扩容，扩容的话那么就要涉及到其中元素的一个迁移，在jdk1.7中，是重新对元素进行计算hash值来进行迁移的；在jdk8中做了比较巧妙的优化，是拿以前的hash值 &amp; 扩容长度 若是=0，那么不动，若是=1那么进行迁移，在原来的位置上加上扩容的长度进行迁移即可。</p><h4 id="_4、hashmap7扩容产生死循环问题有了解过吗" tabindex="-1"><a class="header-anchor" href="#_4、hashmap7扩容产生死循环问题有了解过吗" aria-hidden="true">#</a> 4、HashMap7扩容产生死循环问题有了解过吗？</h4><blockquote><p>简述</p></blockquote><p>先说下何时发生，是在并发情况下进行resize()扩容过程中造成链表成环，之后调用get()方法获取该链上的值时发生的死循环。</p><p>如何构成呢？若是有两个线程同时对一个链进行扩容操作，当对应的e以及next同时指定后，线程1先抢占到了时间片率先完成了扩容，此时由于1.7是头插法，由刚好是扩容到同一个链表中，此时e与next的顺序已经发生了转变，此时线程2抢到时间片继续完成扩容，实际上是对同一个链表上的元素再次进行扩容，此时计算到的新的hash位置同样是该链的位置，就导致其e的next指向该链的头部，此时就构成了环。</p><p>Jdk8解决方案：①采用尾插法，避免了环链的造成。②计算迁移的hash方法发生变化。</p><blockquote><p>分析：<a href="https://www.bilibili.com/video/BV1n541177Ea?spm_id_from=333.337.search-card.all.click" target="_blank" rel="noopener noreferrer">JDK7的HashMap头插法循环的问题，这么难理解吗？<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>、<a href="https://blog.csdn.net/xzq19920203/article/details/106965816?spm=1001.2101.3001.6650.2&amp;utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-2.pc_relevant_antiscanv2&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-2.pc_relevant_antiscanv2&amp;utm_relevant_index=5" target="_blank" rel="noopener noreferrer">hashmap8如何解决hashmap7中的环链问题<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></p></blockquote><p>并发环境情况下，进行put操作其中的refresh过程会造成循环链表，导致之后get()对某个数组链表中的循环链表进行查询造成死循环让线程挂掉。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">//扩容</span>
<span class="token keyword">void</span> <span class="token function">resize</span><span class="token punctuation">(</span><span class="token keyword">int</span> newCapacity<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token class-name">Entry</span><span class="token punctuation">[</span><span class="token punctuation">]</span> oldTable <span class="token operator">=</span> table<span class="token punctuation">;</span><span class="token comment">//哈希数组</span>
    <span class="token keyword">int</span> oldCapacity <span class="token operator">=</span> oldTable<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>oldCapacity <span class="token operator">==</span> MAXIMUM_CAPACITY<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        threshold <span class="token operator">=</span> <span class="token class-name">Integer</span><span class="token punctuation">.</span>MAX_VALUE<span class="token punctuation">;</span>
        <span class="token keyword">return</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token class-name">Entry</span><span class="token punctuation">[</span><span class="token punctuation">]</span> newTable <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Entry</span><span class="token punctuation">[</span>newCapacity<span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//数组实例化</span>
    <span class="token function">transfer</span><span class="token punctuation">(</span>newTable<span class="token punctuation">,</span> <span class="token function">initHashSeedAsNeeded</span><span class="token punctuation">(</span>newCapacity<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    table <span class="token operator">=</span> newTable<span class="token punctuation">;</span>
    threshold <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span><span class="token class-name">Math</span><span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span>newCapacity <span class="token operator">*</span> loadFactor<span class="token punctuation">,</span> MAXIMUM_CAPACITY <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">//将所有条目从当前表转移到新表。</span>
<span class="token keyword">void</span> <span class="token function">transfer</span><span class="token punctuation">(</span><span class="token class-name">Entry</span><span class="token punctuation">[</span><span class="token punctuation">]</span> newTable<span class="token punctuation">,</span> <span class="token keyword">boolean</span> rehash<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">int</span> newCapacity <span class="token operator">=</span> newTable<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
    <span class="token comment">//遍历旧桶数组</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">Entry</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">K</span><span class="token punctuation">,</span><span class="token class-name">V</span><span class="token punctuation">&gt;</span></span> e <span class="token operator">:</span> table<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">while</span><span class="token punctuation">(</span><span class="token keyword">null</span> <span class="token operator">!=</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">//先记录下一次循环要插入的节点</span>
            <span class="token class-name">Entry</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">K</span><span class="token punctuation">,</span><span class="token class-name">V</span><span class="token punctuation">&gt;</span></span> next <span class="token operator">=</span> e<span class="token punctuation">.</span>next<span class="token punctuation">;</span><span class="token comment">//指向旧链表中的下一个节点</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>rehash<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                e<span class="token punctuation">.</span>hash <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token operator">==</span> e<span class="token punctuation">.</span>key <span class="token operator">?</span> <span class="token number">0</span> <span class="token operator">:</span> <span class="token function">hash</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>key<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token comment">//计算新下标</span>
            <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token function">indexFor</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>hash<span class="token punctuation">,</span> newCapacity<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">//下面这两步很明显了，头插法。即先拿到桶原本指向的节点，把要插入的节点的next指向它，然后再把桶指向这个要插入的节点</span>
            e<span class="token punctuation">.</span>next <span class="token operator">=</span> newTable<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
            newTable<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> e<span class="token punctuation">;</span>
            <span class="token comment">//next记录了旧数组旧链表里的下一个节点，现在把e指向它，准备下次循环把它插到新桶</span>
            e <span class="token operator">=</span> next<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>核心问题</strong>：在进行resize扩容的并发过程中容易出现链表成环的一个问题，造成之后get()方法去取值遍历链表时出现死循环的一个问题。</p><p><strong>直击要点</strong>：并发情况下，已经进行resize()过后的元素进行第二次计算新的hash位置时，由于对应的hash位置为自己当前的bucket位置，那么此时进行一个迁移那么就会出现一个列表成环的问题。</p><p>那么到底是如何形成链表成环的呢？</p><p>此时模拟两个线程同时e、next指向同一个元素。</p><p><img src="https://pictured-bed.oss-cn-beijing.aliyuncs.com/img/2022/6/202206151553437.png" alt="image-20220419214125969" loading="lazy"></p><p>这时候第一个线程将扩容操作全部完成了，此时所有的元素都在新的链表上：注意由于是头插法，并且他们都分配到了同一个数组下标时顺序已经是反过来的了</p><p><img src="https://pictured-bed.oss-cn-beijing.aliyuncs.com/img/2022/6/202206151553488.png" alt="image-20220419214443867" loading="lazy"></p><p>接着线程2进行取得时间片继续执行，可以看到因为头插法顺序是反过来的了首先保存下next = e2.next，接着来计算key为3的一个hash求得新数组的下标，此时依旧是在当前数组槽中，此时e2.next = table[i]，此时指向的就是自己当前的链上，之后table[i] = e此时不会有问题，但是已经构成环的情况了。</p><p><img src="https://pictured-bed.oss-cn-beijing.aliyuncs.com/img/2022/6/202206151553537.png" alt="image-20220419214720492" loading="lazy"></p><p>之后使用get()获取指定的元素时，若是刚好hash在该entry中，在进行遍历时就会出现死循环的情况，导致线程结束。</p><h3 id="与其他map区别" tabindex="-1"><a class="header-anchor" href="#与其他map区别" aria-hidden="true">#</a> 与其他Map区别</h3><h4 id="_1、hashmap、linkedhashmap、treemap的底层区别" tabindex="-1"><a class="header-anchor" href="#_1、hashmap、linkedhashmap、treemap的底层区别" aria-hidden="true">#</a> 1、HashMap、LinkedHashMap、TreeMap的底层区别</h4><p>LinkedHashMap继承了HashMap，其具有HashMap的所有功能，再此基础上多维护了一个双向链表，其通过实现HashMap预留的几个回调接口，来存储每个插入结点的顺序，那么与此同时内存使用会比HashMap更大，性能会差一些。若是我们想要对HashMap插入的数据进行一个有序获取，那么就可以使用该Map。</p><p>TreeMap的底层是红黑树，若是需要有序Map可以使用其，主要是根据key来进行排序，默认是升序排序，我们可以实现一个Comparator接口。</p><h4 id="_2、红黑树与avl树比较-红黑树与b树、b-树区别" tabindex="-1"><a class="header-anchor" href="#_2、红黑树与avl树比较-红黑树与b树、b-树区别" aria-hidden="true">#</a> 2、红黑树与AVL树比较？红黑树与B树、B+树区别？</h4><p>首先从时间复杂度上来红黑树与AVL树都是相同的O(logn)，红黑树是保持一个相对的平衡，那么对应AVL对于平衡是较为严格的，左子树与右子树之间高度差不会超过1。<strong>当在进行插入与删除时，若是不平衡红黑树左旋右旋次数最多为3次</strong>，而对于AVL则是多次，由此红黑树的插入效率更高，所以红黑树适合于增删频繁，AVL适合查询频繁，远远大于插入、删除的情况。</p><p>区别：红黑树使用场景一般为内存中，其具有较为复杂的规则，主要就是为了保证树的平衡性，保证平衡性也就是尽可能让树的高度降低；B树是多路查找树，一般对于文件系统索引会使用B树，由于文件索引数据量很大肯定不能够一次性的加载到内存中，所以选择B树是较好的选择，每次从磁盘中加载B树的一个结点，一步步往下找，由此若是在内存中，RB树更优，若是涉及磁盘则选择B树。</p><p>B+树是在B树的基础上进行改良，所有的数据都在叶子结点，其他中间结点主要是用来作索引，并且各个叶子结点之间有指针相连形成链表，改造成这样的目的主要是应对数据库中经常进行的范围查询、分页等，采用B+树就不需要跨层去读取，而是直接在一层上通过链表的方式来进行读取。</p><h4 id="_3、hashmap中底层的红黑树、与其他树进行比较" tabindex="-1"><a class="header-anchor" href="#_3、hashmap中底层的红黑树、与其他树进行比较" aria-hidden="true">#</a> 3、HashMap中底层的红黑树、与其他树进行比较</h4><p>当链表长度大于阈值（默认为8）时，将链表转 化为<a href="https://so.csdn.net/so/search?q=%E7%BA%A2%E9%BB%91%E6%A0%91&amp;spm=1001.2101.3001.7020" target="_blank" rel="noopener noreferrer">红黑树<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>，以减少搜索时间。</p><p>TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷，因为 二叉查找树在某些情况下会退化成一个线性结构。</p><blockquote><p>红黑数的特点</p></blockquote><div class="language-text ext-text line-numbers-mode"><pre class="language-text"><code>1. 每个节点非红即黑；
2. 根节点总是黑色的；叶子结点是黑色的。
3、每个红色结点的左右结点都是黑色。（保证了从根节点到叶子结点不会出现连续两个红色结点）
4. 从根节点到叶节点或空子节点的每条路径，必须包含相同数目的黑色节点（即相同的黑色高度）
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>应用</strong>： TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。</p><p><strong>为什么要用红黑树</strong> ：简单来说红黑树就是为了解决二叉查找树的缺陷，因为二叉查找树在某些情况下会退化成一个线性结构。</p><p><strong>红黑树这么优秀,为何不直接使用红黑树得了</strong>：红黑树属于（自）平衡二叉树，但是为了保持“平衡”是需要付出代价的， 红黑树在插入新数据后可能需要通过左旋，右旋、变色这些操作来保持平衡，这费事啊。我们引入红黑树就是 为了查找数据快，如果链表长度很短的话，根本不需要引入红黑树的，你引入之后还要付出代价维持它的平衡。但是链表过长就不一样了。至于为什么选 8 这个值呢？通过概率统计所得，这个值是综合查询成本和新增元素成本得出的 最好的一个值。</p><blockquote><p>红黑树与AVL的比较</p><p><a href="https://blog.csdn.net/zkkzpp258/article/details/123019720" target="_blank" rel="noopener noreferrer">红黑树与AVL树的区别<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>、<a href="https://blog.csdn.net/YMY_mine/article/details/81517618?spm=1001.2101.3001.6650.3&amp;utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-3.pc_relevant_default&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-3.pc_relevant_default&amp;utm_relevant_index=5" target="_blank" rel="noopener noreferrer">红黑树与AVL树区别<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></p></blockquote><p>红黑树：红黑树是一种自平衡二叉查找树(又称为二叉B树)，在插入和删除操作时通过特定操作(左旋、右旋)保持二叉查找树的平衡，从而获得较高的查找性能。</p><ul><li>时间复杂度为O(logn)</li><li>插入、删除而造成的恢复平衡次数最多为3次，时间复杂度只需要O(1)。 <ul><li>对于平衡并不是十分严格，任何不平衡的情况在三次选中中就会解决，不追求&quot;完全平衡&quot;，只要求部分平衡，降低对旋转的要求，提升了性能。</li></ul></li><li>应用场景：HashMap、TreeMap、实现关联数组。</li></ul><p>AVL树：AVL树是最先发明的自平衡二叉查找树。树的平衡也是通过左旋和右旋进行维持。插入删除时可能经过一次或多次左旋右旋，慢动作看<a href="https://so.csdn.net/so/search?q=%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84&amp;spm=1001.2101.3001.7020" target="_blank" rel="noopener noreferrer">数据结构<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>可视化可以看到插入某一元素后，先调整高度，然后可能经过两次左旋。</p><ul><li>定义：①左子树和右子树的高度差不能超过1 。②它的左子树和右子树都是AVL树 。</li><li>时间复杂度为O(logn)</li><li>插入删除时可能经过一次或多次左旋右旋，先调整高度，然后可能经过两次左旋，旋转的次数要比红黑树更多。</li><li>用途：windows对进程地址空间管理。</li></ul><p>差别：</p><p>1、RB树的插入效率更高，其恢复平衡旋转的次数更少。</p><p>2、RB树算法时间度与AVL相同，但是统计性能比AVL树更高。</p><p>3、在实际应用中，若是搜索次数远远大于插入与删除，那么选择AVL；如果搜索、插入、删除次数差不多就选择RB。若是查询、插入以及删除次数几乎差不多，那就选择红黑树。</p><p><img src="https://pictured-bed.oss-cn-beijing.aliyuncs.com/img/2022/6/202206151553068.png" alt="image-20220419173032948" loading="lazy"></p><blockquote><p>红黑树与B+树区别</p></blockquote><p>B+树常用于数据库和文件系统中，B+树能够保持数据稳定有序，其插入与修改拥有较稳定的对数时间复杂度。B+ 树自底向上插入，这与二叉树恰好相反。</p><p>B+树与B树的主要区别：</p><p>1、B+树中只有叶子节点会带有指向记录的指针，而B树所有节点都有指针，在内部节点出现的索引项不会再出现在叶子节点中。（B+树的所有全量数据都在叶子节点，而B树每个节点都是全量数据）</p><p>2、B+树中所有叶子节点都是通过指针连接在一起，而B树不会。</p><p>区别：</p><p>1、红黑树结构数据常常存在于主存中，主要用于快速查找，树的每个结点存储的数据量少，CPU与主存少量的交互就能够获取树的全部数据，快速查找数据。</p><p>2、B+树形式数据主要存储于SSD或磁盘中，由于树的深度较小，能够尽可能的减少CPU与磁盘的交互时间。</p><blockquote><p>红黑树、B树、B+树区别</p></blockquote><p>红黑树是平衡树的一种，对其进行复杂的定义与规则，主要是为了保证树的平衡性。</p><ul><li>为什么要保证平衡性呢？因为树的查找性能依据取决于树的高度，为了保证树的平衡性，就是降低树的高度。</li></ul><p>B树一般用在文件系统索引上，为什么文件索引需要使用B树，而不是B+树？</p><ul><li>文件系统和数据库的索引都是存在硬盘上的，并且如果<strong>数据量大的话，不一定能一次性加载到内存</strong>，那么显然内存都加载不了自然也就何谈查找呢？此时B树的多路存储能力就出来了，通过每次从磁盘中加载B树的一个节点，来一步步往下找。</li><li>为什么设计成多路呢？降低树的高度，路数越多，树的高度就越低。</li></ul><p>小总结：<strong>B树与红黑树比较：若是在内存中，红黑树更优；若是涉及到磁盘中，B树更优。</strong></p><p>B+树：是在B树的基础上进行改造，数据全部都在叶子结点，并且各个叶子结点增加了指针形成链表。</p><ul><li>应用场景：数据库数据存储。</li><li>为什么这么设计？数据库中 Select 数据，不一定只选一条，很多时候会选多条，比如按照 ID 排序后选 10 条。如果是多条的话，B树需要做局部的中序遍历，可能还要跨层访问，而B+树由于所有数据都在叶子节点，不用跨层，同时由于有链表结构，只需要找到首尾，通过链表就能把所有数据取出来了。</li></ul><h2 id="concurrenthashmap" tabindex="-1"><a class="header-anchor" href="#concurrenthashmap" aria-hidden="true">#</a> ConcurrentHashMap</h2><h3 id="_1、介绍下concurrenthashmap" tabindex="-1"><a class="header-anchor" href="#_1、介绍下concurrenthashmap" aria-hidden="true">#</a> 1、介绍下ConcurrentHashMap</h3><p>Jdk1.7版本中，采用了分段锁技术，其是一个segement数组，每个数组中包含了多个HashEntry，Segment通过继承ReentrantLock来进行加锁，在通过每次锁住一个segment来保证每个segment操作的线程安全，底层依旧是数组+链表。</p><p>JDK1.8：在jdk1.7中虽然解决并发的问题，但是依然有查询遍历链表效率低的一个问题，结构上也发生改变，将原有的segment分段锁加锁替换为了cas+synchronized来保证并发的一个安全性，并将hashEntry更改为了Node节点，对于其中的哈希表以及Node节点中的属性都加上了volatile，保证了可见性。底层依旧是数组+链表+红黑树。</p><blockquote><p>结构组成</p></blockquote><p>同样也是数组 + 链表 + 红黑树 构成</p><p>同样也是由Node[]结构构成的一个Map，在Node结点中实现了Entry接口，具有key、value、hash值以及维护一个next指针，用于之后形成一个链表。</p><h3 id="_2、介绍下put方法-1-8" tabindex="-1"><a class="header-anchor" href="#_2、介绍下put方法-1-8" aria-hidden="true">#</a> 2、介绍下put方法（1.8）</h3><p>首先判断key、value是否为null，若是抛出空指针，不是就继续向下执行。接着会计算机key的一个散列hash(高16位异或低16位)。接着有一个for循环主要目的是不断进行循环cas操作，主要是防止其中cas失败的一个情况。进入for循环会进行判断初始化表，接着使用cas来获取表中执行哈希索引的Node节点，若key与当前的节点相同那么就进行cas替换操作，之后实际将值插入到链表或树中是在一个synchronized同步锁中实现的，在插入节点之后会有一个判断节点是否需要转为红黑树逻辑以及是否需要扩容。</p><h3 id="_3、介绍下get方法-1-8" tabindex="-1"><a class="header-anchor" href="#_3、介绍下get方法-1-8" aria-hidden="true">#</a> 3、介绍下get方法（1.8）</h3><p>在get方法中是没有出现加锁的情况，进入首先会看表是否为空，不为空的话会去比较一下当前索引下标的节点是否为我们要找的节点，若是没有回去判断hash值是否&lt;0，小于0的话有多个值（-1到扩容迁移的表中查找，-2到红黑树中找），若是&gt;0，则会去遍历链表，直接返回查找到的值。</p><p>get操作采用的是CAS操作。</p><h3 id="_4、get中没有加锁的话-如何保证读到的数据不是脏数据呢" tabindex="-1"><a class="header-anchor" href="#_4、get中没有加锁的话-如何保证读到的数据不是脏数据呢" aria-hidden="true">#</a> 4、get中没有加锁的话，如何保证读到的数据不是脏数据呢？</h3><p>在concurrenthashmap中对于table、node节点、treebin中都设置了volatile，如node节点中的value、next指针。<strong>引出volatile</strong></p><p>若是对声明了volatile的变量进行写操作，那么jvm就会向处理器发送一个指令，这个指令就会将所在缓存行的值刷新回到主存。此时就又有一个问题，若是其他处理器的值依旧是旧的，那么执行计算操作还是有问题。</p><p>所以在多处理器下，为了保证多个处理器的缓存是一致的，就会实现缓存一致性，当某个CPU在进行写数据的时候，若是发现该操作变量是共享变量，就会通知其他CPU告知该变量的缓存行是无效的，此时就会重新去主存中加载数据。</p><h3 id="_5、为什么concurrenthashmap中使用cas-synchronized" tabindex="-1"><a class="header-anchor" href="#_5、为什么concurrenthashmap中使用cas-synchronized" aria-hidden="true">#</a> 5、为什么concurrenthashmap中使用cas+synchronized？</h3><p>在1.8之前，使用的是segment数组，每个segment中继承了Reentrantlock，也就是每个segment都是一个锁，在一个segment中又有一个entry table数组，每个table数组中对应的索引数据对应着一个Node链表，在进行put操作时实际上就是以segment为单位上锁进行操作，这里上锁使用的时Reentrantlock。</p><p>Jdk1.8使用的时cas+synchronized，get取用的时cas，插入操作时synchronized，这里synchronized(f)锁的对象同样也是哈希数组中的某个节点，在jdk1.8synchronized是有锁升级的。</p><p>由于锁目前已经十分细化了，哪怕出现竞争，这个时间肯定是能够有限自旋次数之内的，若是在自旋过程中获取到了锁，那么实际上就省去了一个上下文开销的时间，而对于reentrantlock锁仅仅只是做了一次尝试上锁后线程就会放入到阻塞队列当中，就是会阻塞，此时就有很多的上下文切换开销，所以synchronized相对来说是更好的一个选择。</p><h3 id="_6、concurrenthashmap负载因子可以指定吗" tabindex="-1"><a class="header-anchor" href="#_6、concurrenthashmap负载因子可以指定吗" aria-hidden="true">#</a> 6、ConcurrentHashMap负载因子可以指定吗？</h3><p>在HashMap中是可以进行赋值的，不是说修改：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">//常量</span>
<span class="token keyword">final</span> <span class="token keyword">float</span> loadFactor<span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token class-name">HashMap</span><span class="token punctuation">(</span><span class="token keyword">int</span> initialCapacity<span class="token punctuation">,</span> <span class="token keyword">float</span> loadFactor<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>loadFactor <span class="token operator">=</span> loadFactor<span class="token punctuation">;</span><span class="token comment">//允许赋值</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>threshold <span class="token operator">=</span> <span class="token function">tableSizeFor</span><span class="token punctuation">(</span>initialCapacity<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>ConcurrentHashMap是不能够进行指定的，固定值是0.75，虽然提供了一个可传入负载因子的构造器，但是并没有进行指定。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token class-name">ConcurrentHashMap</span><span class="token punctuation">(</span><span class="token keyword">int</span> initialCapacity<span class="token punctuation">,</span>
                         <span class="token keyword">float</span> loadFactor<span class="token punctuation">,</span> <span class="token keyword">int</span> concurrencyLevel<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token punctuation">(</span>loadFactor <span class="token operator">&gt;</span> <span class="token number">0.0f</span><span class="token punctuation">)</span> <span class="token operator">||</span> initialCapacity <span class="token operator">&lt;</span> <span class="token number">0</span> <span class="token operator">||</span> concurrencyLevel <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span>
        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>initialCapacity <span class="token operator">&lt;</span> concurrencyLevel<span class="token punctuation">)</span>   <span class="token comment">// Use at least as many bins</span>
        initialCapacity <span class="token operator">=</span> concurrencyLevel<span class="token punctuation">;</span>   <span class="token comment">// as estimated threads</span>
    <span class="token comment">//仅仅是在这边来求取size容量，并没有赋值动作</span>
    <span class="token keyword">long</span> size <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">long</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">1.0</span> <span class="token operator">+</span> <span class="token punctuation">(</span><span class="token keyword">long</span><span class="token punctuation">)</span>initialCapacity <span class="token operator">/</span> loadFactor<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">int</span> cap <span class="token operator">=</span> <span class="token punctuation">(</span>size <span class="token operator">&gt;=</span> <span class="token punctuation">(</span><span class="token keyword">long</span><span class="token punctuation">)</span>MAXIMUM_CAPACITY<span class="token punctuation">)</span> <span class="token operator">?</span>
        MAXIMUM_CAPACITY <span class="token operator">:</span> <span class="token function">tableSizeFor</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>size<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>sizeCtl <span class="token operator">=</span> cap<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在HashMap中并没有对应的loadFactor，在segment是有的：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Segment</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">K</span><span class="token punctuation">,</span><span class="token class-name">V</span><span class="token punctuation">&gt;</span></span> <span class="token keyword">extends</span> <span class="token class-name">ReentrantLock</span> <span class="token keyword">implements</span> <span class="token class-name">Serializable</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> serialVersionUID <span class="token operator">=</span> <span class="token number">2249069246763182397L</span><span class="token punctuation">;</span>
    <span class="token comment">//加载因子</span>
    <span class="token keyword">final</span> <span class="token keyword">float</span> loadFactor<span class="token punctuation">;</span>
    <span class="token class-name">Segment</span><span class="token punctuation">(</span><span class="token keyword">float</span> lf<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>loadFactor <span class="token operator">=</span> lf<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></div><!----><footer class="page-meta"><div class="meta-item edit-link"><a href="https://gitee.com/changluJava/personal-reading/edit/main/demo/src/zh/interview/Java容器.md" rel="noopener noreferrer" target="_blank" aria-label="编辑此页" class="nav-link label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon edit-icon" viewbox="0 0 1024 1024" fill="currentColor" aria-label="edit icon"><path d="M430.818 653.65a60.46 60.46 0 0 1-50.96-93.281l71.69-114.012 7.773-10.365L816.038 80.138A60.46 60.46 0 0 1 859.225 62a60.46 60.46 0 0 1 43.186 18.138l43.186 43.186a60.46 60.46 0 0 1 0 86.373L588.879 565.55l-8.637 8.637-117.466 68.234a60.46 60.46 0 0 1-31.958 11.229z"></path><path d="M728.802 962H252.891A190.883 190.883 0 0 1 62.008 771.98V296.934a190.883 190.883 0 0 1 190.883-192.61h267.754a60.46 60.46 0 0 1 0 120.92H252.891a69.962 69.962 0 0 0-69.098 69.099V771.98a69.962 69.962 0 0 0 69.098 69.098h475.911A69.962 69.962 0 0 0 797.9 771.98V503.363a60.46 60.46 0 1 1 120.922 0V771.98A190.883 190.883 0 0 1 728.802 962z"></path></svg><!--]-->编辑此页<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><!----><!----></footer><nav class="page-nav"><a href="/zh/interview/Java%E5%9F%BA%E7%A1%80.html" class="nav-link prev" aria-label="JAVA"><div class="hint"><span class="arrow left"></span>上一页</div><div class="link"><span class="icon iconfont icon-lock" style=""></span>JAVA</div></a><a href="/zh/interview/JUC.html" class="nav-link next" aria-label="JUC"><div class="hint">下一页<span class="arrow right"></span></div><div class="link">JUC<span class="icon iconfont icon-lock" style=""></span></div></a></nav><div class="giscus-wrapper input-top" style="display:block;"><div style="text-align:center">Loading...</div></div><!----><!--]--></main><!--]--><footer class="footer-wrapper"><div class="footer">默认页脚</div><div class="copyright">Copyright © 2022 长路</div></footer><!--]--></div><!--]--><!----><!--]--></div>
    <script type="module" src="/assets/app.e732cc94.js" defer></script>
  </body>
</html>
